Почему значение query_hash равно нулю для операторов EXEC?

8

Я настраиваю систему мониторинга для 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для группировки операторов в рамках конкретного выполнения хранимой процедуры, чтобы увидеть, что наиболее дорогостоящая часть процедуры.

Берт Ван Ландегем
источник
2
Я не знаю, почему 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;, вы могли бы получить идентичные дескрипторы плана для них.
Андрей М
У них разные дескрипторы plan_handles, потому что они используются в разных базах данных. Сначала я этого не заметил. В этом случае ссылки на объекты не совпадают, поэтому разные планы. Спасибо за указание.
Берт Ван Ландегем
Если это так, разве это не решит твою проблему? Вы можете генерировать отчеты об активности по базе данных, и вы сможете обнаружить проблемы с прослушиванием / параметризацией параметров с помощью определенных процедур.
Том V - попробуйте topanswers.xyz
Ну да на самом деле ...
Берт Ван Ландегем
3
Если ваша основная проблема действительно была решена, не могли бы вы опубликовать ответ, объясняющий ваши выводы и как это помогло решить проблему? Вам не нужно, но, если это может вдохновить вас каким-либо образом, это может стать ценным вкладом в базу знаний этого сайта. Имейте в виду, что мы предпочитаем хранить комментарии, пока они помогают уточнить вопрос / ответ, поэтому не стесняйтесь повторять любые пункты, уже упомянутые в этих комментариях, чтобы впоследствии их можно было безопасно удалить.
Андрей М

Ответы:

1

Чтобы объяснить, почему хэш создан:

Когда мы отправляем запрос на сервер, процесс algebrizer (да, именно так он и называется) создает хеш, как закодированная подпись, запроса. Хеш - это уникальный идентификатор. Идентификатор является уникальным для любого данного запроса, включая весь текст, который определяет запрос, включая пробелы и возврат каретки, оптимизатор сравнивает хэш с запросами в кеше. Если в кэше существует запрос, соответствующий запросу, поступающему в механизм, вся стоимость процесса оптимизации пропускается, и план выполнения в кэше планов используется повторно.

EXECзапускает хранимую процедуру, которая может изменить свой код, так как SQL Server знает, что ему не нужно сравнивать EXECдля его оптимизации, SQL Server не создает хэш.

Джеймс Роат
источник