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.
fuente

query_hashes 0, pero en cuanto a por qué lasexec 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 fueranexec dbo.spSetUserAuth @userid;, por ejemplo , podría obtener identificadores de plan idénticos para ellos.Respuestas:
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 compararEXECpara optimizarlo, SQL Server no crea un hash.fuente