Я настраиваю систему мониторинга для 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_hash0? Возможно, я где-то упускаю из виду анализатор запросов 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_hash0, но почему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;, вы могли бы получить идентичные дескрипторы плана для них.