¿Por qué el query_hash es cero para las declaraciones EXEC?

8

Estoy configurando un sistema de monitoreo para SQL Server usando Extended Events para encontrar consultas pesadas como 'comentarios de producción' para nuestros desarrolladores. Estoy usando los eventos sp_statement_completedy sql_statement_completed, con filtros de predicado en cpu_time, lecturas lógicas, etc. Esperaba agregar los resultados database_namey query_hashcomo se demostró en numerosos ejemplos en todo Internet, pero en los resultados veo que query_hashes 0 para todas las declaraciones usando EXEC, como en la tabla a continuación (marca de tiempo y consulta abreviada para facilitar la lectura).

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 los resultados tienen un valor plan_handley todos son diferentes, por lo que se están generando muchos planes. Otras declaraciones sin query_hash(que he visto) incluyen ALTERAR ÍNDICE, PUNTO DE CONTROL, ACTUALIZAR ESTADÍSTICAS, TRANSACCIÓN DE COMPROMISO, RECIBIR SIGUIENTE DEL Cursor, algunas INSERTAS, SELECCIONAR @variable, SI (@variable = x).

¿Alguien sabe por qué el query_hashes 0? Probablemente me estoy perdiendo el punto en algún lugar sobre el Analizador de consultas SQL y EXEC, pero no puedo encontrar ninguna pista que me señale en la dirección correcta. Si los resultados que estoy obteniendo son 'normales', entonces, ¿cómo agregar mejor los resultados? ¿La agrupación por declaración no incluiría literales, espacios en blanco, etc., que se eliminan al calcular query_hash?

EDITAR: como lo veo ahora, EXEC SomeStoredProcedureinicia un procedimiento almacenado (obvio), y las declaraciones individuales en ese procedimiento almacenado terminan en la sesión de sp_statement_completedeventos como eventos, y todos tienen un query_hash.

Entonces, para sp_statement_completed(es decir, consultas 'reales'), puedo agregar en query_hash y database_name, y sql_statement_completedsin query_hash (el EXEC SomeStoredProcedure), puedo usar el client_connection_idpara agrupar las declaraciones dentro de una ejecución específica de un procedimiento almacenado, para ver qué es lo más parte costosa del procedimiento.

Bert Van Landeghem
fuente
2
No sé por qué query_hashes 0, pero en cuanto a por qué las exec spSetUserAuth @userid;filas tienen diferentes identificadores de plan: The algorithms to match new SQL statements to existing, unused execution plans in the cache require that all object references be fully qualified.( Fuente ). Si todas esas entradas fueran exec dbo.spSetUserAuth @userid;, por ejemplo , podría obtener identificadores de plan idénticos para ellos.
Andriy M
Tienen diferentes plan_handles porque se usan en diferentes bases de datos, no lo noté al principio. En ese caso, las referencias a objetos no son las mismas, de ahí los diferentes planes. Gracias por señalarlo.
Bert Van Landeghem el
Si ese es el caso, ¿no resolvería su problema? Podría generar informes sobre la actividad por base de datos, y podría detectar problemas de detección / parametrización de parámetros con ciertos procedimientos.
Tom V: prueba topanswers.xyz el
Bueno, sí en realidad ...
Bert Van Landeghem
3
Si su problema subyacente ha sido resuelto, ¿podría publicar una respuesta que explique sus hallazgos y cómo eso ayudó a resolver el problema? No tiene que hacerlo, pero si esto puede inspirarlo de alguna manera, podría ser una valiosa contribución a la base de conocimiento de este sitio. Tenga en cuenta que preferimos mantener los comentarios siempre y cuando ayuden a aclarar la pregunta / respuesta, así que siéntase libre de repetir cualquier punto ya mencionado en estos comentarios para que luego puedan eliminarse de manera segura.
Andriy M

Respuestas:

1

Para explicar por qué se crea el hash:

Cuando enviamos una consulta al servidor, el proceso de algebrizer (sí, así se llama) crea un hash, como una firma codificada, de la consulta. El hash es un identificador único. Un identificador es único para cualquier consulta, incluido todo el texto que define la consulta, incluidos los espacios y los retornos de carro, el optimizador compara el hash con las consultas en la memoria caché. Si existe una consulta en la memoria caché que coincide con la consulta que ingresa al motor, se omite todo el costo del proceso de optimización y se reutiliza el plan de ejecución en la memoria caché del plan.

EXECinicia un procedimiento almacenado que puede tener su cambio de código, ya que SQL Server sabe que no necesita comparar EXECpara optimizarlo, SQL Server no crea un hash.

James Rhoat
fuente