Эта рекурсия как в SQL, так и в PHP кажется посторонней

К сожалению, код защищен моей работой, поэтому я не могу им поделиться.

Мой коллега создал фрагмент кода, предназначенный для выбора данных из реляционной базы данных, содержащей древовидные структуры в реляционном формате.

Пример древовидной структуры выглядит примерно так:

{
    "top_level_node": {
        "meta_info_1": "meta_info_keyword1",
        "meta_info_2": "meta_info_keyword2",
        "meta_info_3": "meta_info_keyword3",
        "meta_info_4": "unique string of data", 

        "main_container": {
            "container_attribute": "container_attribute_keyword",

            "sub_container_1": {
                "container_attribute": "container_attribute_keyword",

                "pattern_1": {
                    "pattern_property_1": "pattern_property_1_keyword",
                    "pattern_property_2": "pattern_property_2_keyword",
                    "pattern_property_3": "unique string of data"
                },

                "pattern_2": {
                    "pattern_property_1": "pattern_property_1_keyword",
                    "pattern_property_2": "pattern_property_2_keyword",
                    "pattern_property_3": "unique string of data"
                }
            },

            "pattern_3": {
                "pattern_property_1": "pattern_property_1_keyword",
                "pattern_property_2": "pattern_property_2_keyword",
                "pattern_property_3": "unique string of data"
            }
        }
    }
}

Код, созданный моим коллегой, включает в себя сначала выполнение 50-строчного рекурсивного запроса CTE, который создает все данные, необходимые для дерева, в линейном формате (1 часть данных на строку).

Затем мой коллега взял эти линейные данные в строки и обошел их с помощью рекурсивной функции PHP, чтобы восстановить древовидную структуру из данных.

Я попытался сказать, что это неправильный подход, потому что:

  1. Данные уже находятся в формате (реляционные таблицы базы данных), который можно использовать для перестроения древовидной структуры с помощью рекурсивной функции php и простых запросов для выбора каждой части данных по мере продвижения. Я утверждаю, что это легче читать и требует только одного рекурсивного цикла.

  2. Это не срочная операция, мы перестраиваем дерево данных для «процесса компиляции», который будет происходить, возможно, раз в месяц. Я утверждаю, что, поскольку время здесь не имеет значения, рекурсивный запрос CTE практически не дает никаких преимуществ.

  3. Запрос очень длинный и сложный для чтения, если кто-то хочет понять, что делает php-код, он должен сначала понять запрос. Я утверждаю, что рекурсия должна быть в коде, а запросы должны быть простыми и понятными, что они извлекают.

Я утверждаю, что теоретически здесь требуется только одна часть рекурсии — либо рекурсивная в SQL, либо рекурсивная в PHP. Я утверждаю, что рекурсию в PHP легче понять, а рекурсия в SQL не способна перестроить древовидную структуру без массивного запроса.

Я прав? Почему, почему нет? Я ошибаюсь? Почему, почему нет? Имеет ли смысл выполнять рекурсивный запрос для преобразования данных из реляционного формата в линейный формат, а затем выполнять другую рекурсивную функцию для преобразования линейных данных в дерево?


person user6567423    schedule 10.12.2018    source источник
comment
Обработка рекурсивных данных без рекурсивных запросов очень часто приводит к большому количеству ненужных запросов. А многие небольшие запросы, обрабатывающие всего несколько строк (или, что еще хуже, всего одну), обычно выполняются медленнее, чем один запрос, обрабатывающий множество строк.   -  person a_horse_with_no_name    schedule 10.12.2018
comment
Да, конечно, это было бы намного медленнее, но, как я уже сказал, это процесс, который запускается локально на серверах нашей компании, может быть, раз в месяц для компиляции некоторых данных в древовидные форматы - это абсолютно не время чувствительный, что является моим главным аргументом в пользу выбора читаемости, а не производительности.   -  person user6567423    schedule 11.12.2018


Ответы (1)


Ваш коллега разработал метод, который позволяет ему извлекать данные для рекурсивной структуры одним запросом. Для этого могут быть веские технические причины. Его запрос является рекурсивным, потому что это разумный метод сведения древовидной структуры данных в таблицу. Затем он строит новое дерево по другую сторону от этой таблицы данных, снова рекурсивная операция, потому что это дерево, которое он строит.

Чтобы удалить одну или обе рекурсии, вы должны ответить на вопрос «как я могу написать один запрос, который возвращает все данные в рекурсивной структуре, не требующей выравнивания?» В качестве альтернативы вы можете отказаться от идеи плоского списка и получать данные для каждой ветви (и каждой ветви каждой ветви) в отдельных запросах. Я подозреваю, что его подход намного быстрее.

Короче говоря, вы не правы и не ошибаетесь. «Правильный» подход — это тот, который лучше всего удовлетворяет функциональным и нефункциональным требованиям вашего программного обеспечения (для некоторого определения «наилучшего»), каким бы этот подход ни был. При принятии такого рода решений всегда возникают компромиссы. Чтобы получить желаемую скорость, вам, возможно, придется пожертвовать читабельностью, краткостью и ремонтопригодностью кода. Вот как это работает.

person Robert Harvey    schedule 10.12.2018
comment
Спасибо за вклад, просто чтобы обсудить некоторые моменты, которые вы сделали: как я могу написать один запрос, который возвращает все данные в рекурсивной структуре, которая не требует выравнивания? На самом деле нет... PHP может быть рекурсивным и выполнять простые запросы для выбора каждого элемента данных, которые перестраивают дерево. Мы не ограничены одним запросом, и на самом деле я считаю, что использование одного запроса снижает удобочитаемость, но повышает производительность в ситуации, когда производительность не важна. - person user6567423; 10.12.2018
comment
Тогда у вас есть ответ. - person Robert Harvey; 10.12.2018