Должен ли я использовать сложные запросы SQL или обрабатывать результаты в приложении? - PullRequest
9 голосов
/ 02 сентября 2011

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

Мне было интересно, будет ли хорошей практикой извлекать больше данных из базы данных и делать последний запрос в моем коде,скажем, с Python.Я чокнутый?Будет ли это так плохо для производительности?

Обратите внимание, результаты тоже огромны, я говорю о ERP в производстве, разработанном другими людьми.

Ответы [ 5 ]

7 голосов
/ 02 сентября 2011

Позвольте БД выяснить, как лучше всего получить нужную информацию, иначе вам придется дублировать функциональность СУБД в вашем коде, и это будет намного сложнее, чем ваши запросы SQL.

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

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

3 голосов
/ 02 сентября 2011

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

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

Обычные Операции OLTP не требуют большого объема данных.База данных может быть огромной, но данные, необходимые для типичной транзакции, будут (как правило) очень маленькой ее частью.Запрос этого в большой базе данных может вызвать проблемы с производительностью, но вы можете оптимизировать это несколькими способами (индексы, полнотекстовый поиск, избыточность, сводные таблицы ... зависит от вашей реальной проблемы).

Каждое правило имеет исключения, но, как общее руководство , постарайтесь включить свою бизнес-логику в код приложения.Хранимые процедуры для сложной логики.Отдельное хранилище данных или набор процедур для отчетности.

1 голос
/ 02 сентября 2011

@ Нивас, как правило, правильный.

Это довольно распространенные модели

  1. Разделение труда - администраторы баз данных должны возвращать все данные, которые нужны бизнесу, но у них есть только база данных для работы. Разработчики могут работать с администраторами баз данных, чтобы сделать это лучше, но ответственность отдела делает это практически невозможным. Таким образом, SQL используется для извлечения данных.

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

Итак, в общем случае, получение данных из базы данных - это все в базу данных. Но если запрос SQL слишком длинный, СУРБД будет сложно его оптимизировать, и это, вероятно, означает, что запрос охватывает данные, бизнес-логику и даже представление за один раз.

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

Но если вы смотрите на ERP в производстве, ограничения и решения, описанные выше, возможно, уже существуют - вы говорите с нужными людьми?

1 голос
/ 02 сентября 2011

По моему опыту, вы должны позволить базе данных выполнять обработку. Это будет намного быстрее, чем сначала получить все данные из базы данных, и у них будет код для объединения и фильтрации результатов.

Сложной частью здесь является документирование ваших запросов, чтобы кто-то еще (или даже вы) понял, что происходит, если вы посмотрите на них через некоторое время. Я обнаружил, что большинство баз данных допускают комментарии в SQL. Иногда между / * comment * / tags и иногда комментируя строку с - comment.

Документированный запрос может выглядеть следующим образом

select name, dateofbirth from (
-- The next subquery will retrieve ....
    select ....
) SR /* SR SubResults */
....
0 голосов
/ 05 октября 2014

Одно из моих приложений (B) использует tempdb для разделения сложных запросов на пакетные. Другое приложение (B) использует сложные запросы без этого.

Приложение A более эффективно для больших БД.

Но чтобы взглянуть на вашу ситуацию, вы можете выполнить сценарий DMV следующим образом:

-- Get top total worker time queries for entire instance (Query 38) (Top Worker Time Queries)
SELECT TOP(50) DB_NAME(t.[dbid]) AS [Database Name], t.[text] AS [Query Text],  
qs.total_worker_time AS [Total Worker Time], qs.min_worker_time AS [Min Worker Time],
qs.total_worker_time/qs.execution_count AS [Avg Worker Time], 
qs.max_worker_time AS [Max Worker Time], qs.execution_count AS [Execution Count], 
qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], 
qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], 
qs.total_physical_reads/qs.execution_count AS [Avg Physical Reads], 
qp.query_plan AS [Query Plan], qs.creation_time AS [Creation Time]
FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp 
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

тогда вы можете открыть план запроса для тяжелого запроса и попытаться найти что-то вроде:

StatementOptmEarlyAbortReason = "TimeOut" или же StatementOptmEarlyAbortReason = "MemoryLimitExceeded"

Эти факты говорят о том, что вы можете разбить сложный запрос на пакетный + tempdb

PS. Он работает для хороших запросов без сканирования индекса / таблицы, отсутствия индексов и т. Д.

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