Я настраиваю систему мониторинга для SQL Server, используя расширенные события, чтобы найти тяжелые запросы в качестве «производственной обратной связи» для наших разработчиков. Я использую событие sp_statement_completed
и sql_statement_completed
, с предикатными фильтрами на cpu_time, логическое чтение и т.д. Я надеялся агрегировать результаты на database_name
и , query_hash
как показаны на многочисленных примеры по всему интернету, но в результатах я вижу , что query_hash
это 0 для всех операторов используя EXEC, как показано в таблице ниже (временная метка и хеш-запрос сокращены для удобства чтения).
name timestamp query_hash plan_handle statement
sql_statement_completed 2016...6414 0 050056019600764... exec Shared.dbo.SyncFirm
sql_statement_completed 2016...9946 0 06003d00e01e730... exec spSetUserAuth @userid;
sql_statement_completed 2016...7184 0 0600e30028c9da0... exec spSetUserAuth @userid;
sp_statement_completed 2016...0409 9826...578 0600c00028e6aa0... SELECT obfuscated_columns FROM dbo.SomeTable
sp_statement_completed 2016...1448 8660...775 060084006d2d660... INSERT INTO dbo.SomeTable ( obfuscated_columns) EXEC(@sql)
sql_statement_completed 2016...7752 0 0600f9006c23f03... exec spSetUserAuth @userid;
sql_statement_completed 2016...1443 1304...641 06005a0008a9b11... select SUBQ.ontrackstatus, COUNT(SUBQ.ontrac
Все результаты имеют значение, plan_handle
и все они разные, поэтому создается много планов. Другие операторы без query_hash
(что я видел) включают ALTER INDEX, CHECKPOINT, UPDATE STATISTICS, COMMIT TRANSACTION, FETCH NEXT FROM Cursor, некоторые INSERT, SELECT @variable, IF (@variable = x).
Кто-нибудь знает, почему query_hash
0? Возможно, я где-то упускаю из виду анализатор запросов SQL и EXEC, но я не могу найти никаких подсказок, указывающих мне правильное направление. Если результаты, которые я получаю, «нормальные», то как лучше агрегировать результаты? Разве группировка по выражению не включает литералы, пробелы и т. Д., Которые удаляются при вычислении query_hash?
РЕДАКТИРОВАТЬ: как я вижу это сейчас, EXEC SomeStoredProcedure
запускает хранимую процедуру (очевидно), и отдельные операторы в этой хранимой процедуре заканчиваются в сеансе sp_statement_completed
событий как события, и все они имеют query_hash.
Таким образом, для sp_statement_completed
(то есть «реальных» запросов) я могу агрегировать по query_hash и database_name, а для sql_statement_completed
без query_hash (EXEC SomeStoredProcedure) я могу использовать команду client_connection_id
для группировки операторов в рамках конкретного выполнения хранимой процедуры, чтобы увидеть, что наиболее дорогостоящая часть процедуры.
источник
query_hash
0, но почемуexec spSetUserAuth @userid;
строки имеют разные дескрипторы плана:The algorithms to match new SQL statements to existing, unused execution plans in the cache require that all object references be fully qualified.
( Источник .) Если бы все эти записи были, напримерexec dbo.spSetUserAuth @userid;
, вы могли бы получить идентичные дескрипторы плана для них.Ответы:
Чтобы объяснить, почему хэш создан:
Когда мы отправляем запрос на сервер, процесс algebrizer (да, именно так он и называется) создает хеш, как закодированная подпись, запроса. Хеш - это уникальный идентификатор. Идентификатор является уникальным для любого данного запроса, включая весь текст, который определяет запрос, включая пробелы и возврат каретки, оптимизатор сравнивает хэш с запросами в кеше. Если в кэше существует запрос, соответствующий запросу, поступающему в механизм, вся стоимость процесса оптимизации пропускается, и план выполнения в кэше планов используется повторно.
EXEC
запускает хранимую процедуру, которая может изменить свой код, так как SQL Server знает, что ему не нужно сравниватьEXEC
для его оптимизации, SQL Server не создает хэш.источник