Intereting Posts
jQuery Autocomplete (Remote) – пример Предел аргументов POST в html или php Графический интерфейс трассировки Xdebug? Как отформатировать дату в PHP без двоеточия в смещении? сохранить изображение из URL-адреса, а затем сохранить его в каталог php Модуль расширения TYPO3 Extbase. Проблема с шаблоном PHP Как рассчитать длину идентификатора сеанса перед началом сеанса Ограничить количество ссылок, показанных с разбиением на страницы Laravel «Строка не может быть проанализирована как XML» ошибка php Автоматическое обновление времени в PHP с помощью Ajax Я хочу загрузить файл и при загрузке файла значения файла должны быть помещены в мой массив Регулярное выражение PHP для коллекции слов вокруг поисковой фразы Как найти разницу в днях между двумя датами CodeIgniter из почтовых данных не проходит Symfony2 – Как получить доступ к службе в пользовательской консоли?

Один SQL-запрос или многие в цикле?

Мне нужно вывести несколько строк из таблицы и обработать их двумя способами:

  • агрегированный по ключу
  • строка за строкой, отсортированная по тому же ключу

Таблица выглядит примерно так:

table ( key, string_data, numeric_data ) 

Поэтому я рассматриваю два подхода к функции, которую я пишу.

Первый будет вытаскивать агрегированные данные с одним запросом, а затем снова запрашивать внутри цикла для каждого набора данных по строкам (следующим является псевдокод, похожий на PHP):

 $rows = query( "SELECT key,SUM(numeric_data) FROM table GROUP BY key" ); foreach ($rows as $row) { <process aggregate data in $row> $key = $row['key']; $row_by_row_data = handle_individual_rows($key); } function handle_individual_rows($key) { $rows = query( "SELECT string_data FROM table WHERE key=?", $key ); <process $rows one row at a time> return $processed_data; } 

Или я мог бы сделать один большой запрос и позволить коду выполнять всю работу:

 $rows = query( "SELECT key, string_data, numeric_data FROM table" ); foreach ($rows as $row) { <process rows individually and calculate aggregates as I go> } 

Производительность не является практической проблемой в этом приложении; Я просто хочу написать разумный и удобный код.

Мне нравится первый вариант, потому что он более модульный – и мне нравится второй вариант, потому что он выглядит структурно простым. Один вариант лучше, чем другой, или это действительно вопрос стиля?

Один SQL запрос, конечно.

Это будет

  • Сохраните много обращений к базе данных
  • Позвольте использовать более эффективные методы GROUP BY

Поскольку ваши агрегаты могут быть одинаково хорошо реализованы в базе данных, это также будет лучше для обеспечения работоспособности: у вас есть вся ваша логика результатов в одном месте.

Ниже приведен пример запроса, который возвращает каждую строку и вычисляет SUM :

 SELECT string_data, numeric_data, SUM(numeric_data) OVER (PARTITION BY key) FROM table 

Обратите внимание, что это, скорее всего, будет использовать параллельный доступ для вычисления SUM для разных key , что вряд ли реализуется в PHP .

Тот же запрос в MySQL :

 SELECT key, string_data, numeric_data, ( SELECT SUM(numeric_data) FROM table ti WHERE ti.key = to.key ) AS key_sum FROM table to 

Если производительность не вызывает беспокойства, я бы пошел со вторым. Кажется мельчайшим бит дружелюбнее.

Если производительность была проблемой, мой ответ был бы «не думаю, профиль» . 🙂

Второй ответ гораздо более ясен, разумен и поддерживается. Вы говорите то же самое с меньшим количеством кода, что обычно лучше.

И я знаю, что вы сказали, что производительность не вызывает беспокойства, но зачем получать данные больше, чем вам нужно?

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

Есть ли что-то о дополнительной обработке, которую вам нужно делать в каждой строке, которая помешала бы вам выражать все в самом SQL-запросе?

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

Другими словами, чем меньше круглых поездок в базу данных, тем лучше.

В зависимости от ваших данных и фактических таблиц вы можете позволить SQL выполнить агрегацию и выбрать все строки, которые вам нужны, с одним запросом.

один запрос sql, вероятно, является лучшей идеей. Это позволяет избежать повторной записи реляционных операций

Я думаю, что вы как-то ответили на свой вопрос, потому что вы говорите, что у вас две разные процедуры: одна агрегировка и одна строка за строкой.

  • если вы хотите, чтобы все было легко читаемым и поддерживаемым, смешение как в одном запросе не звучит правильно, запрос отвечает на две разные потребности, поэтому он не будет очень читабельным

  • даже если перфоманс не является проблемой, быстрее выполнить агрегацию на сервере БД, а не делать это в коде

  • только с одним запросом код, который будет обрабатывать результат, будет смешивать две обработки, обрабатывать строки и вычислительные агрегаты в одно и то же время, поэтому со временем этот код будет запутываться и ошибочно

  • тот же код может развиваться со временем, например, строка за строкой может быть сложной и может создавать ошибки в части агрегации или наоборот

  • если в будущем вам нужно будет разделить эти два метода лечения, будет сложнее распутать код, который в тот момент кто-то еще написал много лет назад …

Относительно соображений производительности с точки зрения ремонтопригодности и удобочитаемости я бы рекомендовал использовать два запроса.

Но имейте в виду, что коэффициент производительности может не быть проблемой на данный момент, но может быть вовремя, когда объем db растет или что-то еще, это никогда не будет незначительным фактором в долгосрочной перспективе …

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