Pourquoi le query_hash est-il nul pour les instructions EXEC?

8

Je suis en train de mettre en place un système de surveillance pour SQL Server en utilisant des événements étendus pour trouver des requêtes lourdes en tant que «retour de production» pour nos développeurs. J'utilise les événements sp_statement_completedet sql_statement_completed, avec des filtres de prédicat sur cpu_time, des lectures logiques, etc. J'espérais agréger les résultats database_nameet query_hashcomme démontré dans de nombreux exemples partout sur Internet, mais dans les résultats, je vois que query_hashc'est 0 pour toutes les instructions en utilisant EXEC, comme dans le tableau ci-dessous (horodatage et queryhash raccourcis pour plus de lisibilité).

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

Tous les résultats ont une valeur pour plan_handleet ils sont tous différents, donc beaucoup de plans sont générés. D'autres instructions sans query_hash(que j'ai vues) incluent ALTER INDEX, CHECKPOINT, UPDATE STATISTICS, COMMIT TRANSACTION, FETCH NEXT FROM Cursor, certains INSERT, SELECT @variable, IF (@variable = x).

Est-ce que quelqu'un sait pourquoi le query_hashest 0? Je manque probablement le point quelque part sur l'Analyseur de requêtes SQL et EXEC, mais je ne suis pas en mesure de trouver des indices pour me diriger dans la bonne direction. Si les résultats que j'obtiens sont «normaux», alors comment agréger au mieux les résultats? Le regroupement par instruction n'inclurait-il pas les littéraux, les espaces blancs, etc., qui sont supprimés lors du calcul de query_hash?

EDIT: comme je le vois maintenant, EXEC SomeStoredProceduredémarre une procédure stockée (évidente), et les instructions individuelles dans cette procédure stockée se retrouvent dans la session d' sp_statement_completedévénement en tant qu'événements , et celles-ci ont toutes un query_hash.

Donc pour sp_statement_completed(c'est-à-dire les «vraies» requêtes), je peux agréger sur query_hash et database_name, et pour sql_statement_completedsans query_hash (EXEC SomeStoredProcedure), je peux utiliser le client_connection_idpour regrouper les instructions dans une exécution spécifique d'une procédure stockée, pour voir ce qui est le plus partie coûteuse de la procédure.

Bert Van Landeghem
la source
2
Je ne sais pas pourquoi query_hashest 0 mais quant à la raison pour laquelle les exec spSetUserAuth @userid;lignes ont des poignées de plan différentes: The algorithms to match new SQL statements to existing, unused execution plans in the cache require that all object references be fully qualified.( Source .) Si toutes ces entrées étaient par exemple exec dbo.spSetUserAuth @userid;, vous pourriez obtenir des poignées de plan identiques pour elles.
Andriy M
Ils ont des plans_handles différents car ils sont utilisés dans différentes bases de données, je ne l'ai pas remarqué au début. Dans ce cas, les références d'objet ne sont pas les mêmes, d'où les différents plans. Merci d'avoir souligné.
Bert Van Landeghem
Si tel est le cas, cela ne résoudrait-il pas votre problème? Vous pouvez générer des rapports d'activité par base de données et vous pourriez détecter des problèmes de reniflage / paramétrage de paramètres avec certaines procédures.
Tom V - essayez topanswers.xyz
Eh bien, oui en fait ...
Bert Van Landeghem
3
Si votre problème sous-jacent a effectivement été résolu, pourriez-vous publier une réponse expliquant vos résultats et comment cela a aidé à résoudre le problème? Vous n'êtes pas obligé mais, si cela peut vous inspirer de quelque manière que ce soit, cela pourrait être une contribution précieuse à la base de connaissances de ce site. Gardez à l'esprit que nous préférons conserver les commentaires aussi longtemps qu'ils aident à clarifier la question / réponse, alors n'hésitez pas à répéter les points déjà mentionnés dans ces commentaires afin qu'ils puissent ensuite être supprimés en toute sécurité.
Andriy M

Réponses:

1

Pour expliquer pourquoi le hachage est créé:

Lorsque nous soumettons une requête au serveur, le processus algébrizer (oui c'est comme ça qu'on l'appelle) crée un hachage, comme une signature codée, de la requête. Le hachage est un identifiant unique. Un identifiant est unique pour toute requête donnée, y compris tout le texte qui définit la requête, y compris les espaces et les retours chariot, l'optimiseur compare le hachage aux requêtes dans le cache. Si une requête existe dans le cache qui correspond à la requête entrant dans le moteur, le coût total du processus d'optimisation est ignoré et le plan d'exécution dans le cache du plan est réutilisé.

EXECdémarre une procédure stockée qui peut voir son code changer, car SQL Server sait qu'il n'a pas besoin de comparer EXECpour l'optimiser, SQL Server ne crée pas de hachage.

James Rhoat
la source