Мне нужно вывести несколько строк из таблицы и обработать их двумя способами:
Таблица выглядит примерно так:
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-запросы элегантны. Вы хотите разработать более элегантный код или более неаккуратный код?