#c_sharp #net #sql_server
Например, есть некоторый сервис, который время от времени выполняет запросы и нужно определить насколько запрос был "тяжелым". По каким критериям это можно оценить? Первое, что пришло на ум- это замерить загрузку процессора на SQL Server до и во время выполнения запроса. По каким критериям еще можно понять, что запрос оказался тяжелым и мог негавтивно сказаться на работу других пользователей с БД? Собственно, это нужно для программы балансировки нагрузки, что бы выполнять тяжелые запросы в наиболее подходящее время. Собственно, не помешал бы минимальный пример, как эту статистику можно получить из когда программы.
Ответы
Ответ 1
Тяжесть зависит от плана выполнения. План выполнения может меняться в зависимости от статистики по таблицам. Статистика может устаревать и порождать неверные планы. Так что "тяжесть" - величина непостоянная. Кроме того, в SQL Server есть кэш данных, и запрос, выбирающий данные их кэша, ес-но будет выдавать меньше физических чтений с диска. Поэтому при замерах стоит смотреть на количество логических чтений, а не только на количество физических. Грубо можно оценить, замерив время и IO напрямую: SET STATISTICS TIME ON SET STATISTICS IO ON запрос Выполнить несколько раз, отбросить максимальное и минимальное значение по CPU, по остальным - взять среднее. Показатели IO будут зависеть от плана, так что они при последовательных выполнениях не поменяются. Для воспроизведения промаха кэша - почистите его вызовом CHECKPOINT; DBCC DROPCLEANBUFFERS; Из .NET значения статистики можно получить, выставлением свойства sqlConnection.StatisticsEnabled = true + вызовом sqlConnection.RetrieveStatistics() Что делать с "плохим" запросом - достаточно обширный вопрос. Минимальный набор действий пересчитать статистику для используемых таблиц(обязательно, иначе есть шанс бороть несуществующую проблему!) получить свежий план выполнения если план плохой - оптимизировать запрос, индексы или структуру базы Что точно не стоит делать - это править SQL наугад. Оптимизация SQL - достаточно простой процесс, но при этом нужно точно представлять механизм выполнения запросов SQL Server, иначе можно получить кучу скрытых проблем :)Ответ 2
Объективный критерий - это замеры статистики при выполнении запроса, PashaPash вам про них уже написал. Но недостаток такого метода заключается в том, что он позволяет только измерять запросы, но не говорит что надо изменить. Поэтому я часто использую альтернативный вариант - просмотр плана выполнения запроса. Его можно получить командой EXPLAIN - но лучше пользоваться соответствующей кнопкой в SQL Mangement Studio и смотреть графический план. Если вы делаете запрос на ограниченное количество строк (используете конструкцию TOP) - то главными врагами будут Sort и Hash Join. Sort полностью вычитывает входные строки перед тем как начать выдавать хоть что-нибудь на выход, Hash Join то же самое делает со своим вторым входом. Оба варианта не позволяют получить от конструкции TOP нормального ускорения для запроса. Также маркером что что-то пошло не так, может выступать конструкция Merge Join, а также упомянутые ранее Sort и Hash Join. Эти операции вполне нормальны для сложных аналитических запросов - но для постоянно используемых запросов их в плане быть не должно. Далее, следует проверить операции класса Scan (Table Scan, Clustered Index Scan и Index Scan). Есть шанс, что оптимизатор запросов не нашел подходящего индекса и просматривает таблицу целиком. Тем не менее, если ваш запрос как раз и запрашивает таблицу целиком - это нормально :-) Также полные сканы обычно неплохо ускоряются при наличии ограничения TOP (но только если они идут по первому, "верхнему" пути в соединении). Чтобы отличить "хороший" скан от плохого, можно посмотреть на его параметры. Если там ничего не указано или указан только Predicate - это полное сканирование таблицы. При указании Range сканируются записи попавшие в некоторый диапазон - тут надо смотреть что это за диапазон, чем он задается и сколько там записей. При указании Prefix сканируются записи, у которых совпадает часть ключа. Также можно просто посмотреть на ожидаемое количество строк.Ответ 3
Приведу два варианта. Программный. Полистав интернет, найдя и модифицировав сложные запросы я сделал себе такие выборки (они показывают тяжёлые запросы, а не конкретный запрос, но как правило свой остаётся какое-то время в кеше) select * from ( select (select text from sys.dm_exec_sql_text(sql_handle)) tx, max(last_execution_time) tm from sys.dm_exec_query_stats group by sql_handle ) t where tx not like '%CREATE PROCEDURE%' order by 1 SELECT text, cp.objtype, cp.size_in_bytes FROM sys.dm_exec_cached_plans AS cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st WHERE cp.cacheobjtype = N'Compiled Plan' AND cp.objtype IN(N'Adhoc', N'Prepared') AND cp.usecounts = 1 ORDER BY cp.size_in_bytes DESC OPTION (RECOMPILE); select (select text from sys.dm_exec_sql_text(sql_handle)) tx, * from sys.dm_exec_requests SELECT objtype AS [CacheType] , count_big(*) AS [Total Plans] , sum(cast(size_in_bytes as decimal(18,2)))/1024/1024 AS [Total MBs] , avg(usecounts) AS [Avg Use Count] , sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(18,2)))/1024/1024 AS [Total MBs — USE Count 1] , sum(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS [Total Plans — USE Count 1] FROM sys.dm_exec_cached_plans GROUP BY objtype ORDER BY [Total MBs — USE Count 1] DESC Вручную можно открыть Activity Monitor. В ранних версиях (2005, 2008) он находится в корне Management в Sql Management Studio, в поздних версиях он в контекстном меню "сервера" в Sql Management Studio.
Комментариев нет:
Отправить комментарий