Estou configurando um sistema de monitoramento para o SQL Server usando Eventos Estendidos para encontrar consultas pesadas como 'feedback de produção' para nossos desenvolvedores. Estou usando os eventos sp_statement_completed
e sql_statement_completed
, com filtros de predicado em cpu_time, leituras lógicas, etc. Eu esperava agregar os resultados database_name
e query_hash
demonstrados em vários exemplos em toda a Internet, mas nos resultados vejo que query_hash
é 0 para todas as instruções usando EXEC, como na tabela abaixo (carimbo de data e hora e consulta reduzidos para facilitar a leitura).
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
Todos os resultados têm um valor para plan_handle
e são todos diferentes, portanto, muitos planos estão sendo gerados. Outras declarações sem query_hash
(que eu já vi) incluem ALTER INDEX, CHECKPOINT, UPDATE STATISTICS, COMMIT TRANSACTION, FETCH NEXT FROM Cursor, alguns INSERTs, SELECT @variable, IF (@variable = x).
Alguém sabe por que o query_hash
é 0? Provavelmente estou perdendo o argumento em algum lugar sobre o SQL Query Analyzer e o EXEC, mas não consigo encontrar nenhuma pista para me indicar a direção certa. Se os resultados que estou tendo são 'normais', como agregar os resultados da melhor maneira? O agrupamento por instrução não incluiria literais, espaços em branco, etc ... que são removidos ao calcular query_hash?
EDIT: como eu vejo agora, EXEC SomeStoredProcedure
inicia um procedimento armazenado (óbvio), e as instruções individuais nesse procedimento armazenado terminam na sessão de sp_statement_completed
eventos como eventos, e todas elas têm um query_hash.
Portanto, para sp_statement_completed
(ou seja, consultas 'reais'), eu posso agregar em query_hash e database_name e, sql_statement_completed
sem query_hash (o EXEC SomeStoredProcedure), posso usar o client_connection_id
para agrupar as instruções em uma execução específica de um procedimento armazenado, para ver o que é mais parte dispendiosa do procedimento.
fonte
query_hash
0 é, mas por que asexec spSetUserAuth @userid;
linhas têm identificadores de plano diferentes:The algorithms to match new SQL statements to existing, unused execution plans in the cache require that all object references be fully qualified.
( Origem .) Se todas essas entradas fossemexec dbo.spSetUserAuth @userid;
, por exemplo , você pode obter identificadores de plano idênticos para eles.Respostas:
Para explicar por que o hash é criado:
Quando enviamos uma consulta ao servidor, o processo de algebrizer (sim, é assim que é chamado) cria um hash, como uma assinatura codificada, da consulta. O hash é um identificador exclusivo. Um identificador é exclusivo para qualquer consulta, incluindo todo o texto que define a consulta, incluindo espaços e retornos de carro; o otimizador compara o hash às consultas no cache. Se existir uma consulta no cache que corresponda à consulta que entra no mecanismo, todo o custo do processo de otimização será ignorado e o plano de execução no cache do plano será reutilizado.
EXEC
inicia um procedimento armazenado que pode ter seu código alterado, uma vez que o SQL Server sabe que não precisa ser comparadoEXEC
para otimizá-lo, o SQL Server não cria um hash.fonte