Estamos solucionando problemas de un servidor que tiene una alta utilización de la CPU. Después de descubrir que las consultas realmente no lo estaban causando, comenzamos a buscar compilaciones.
El Monitor de rendimiento muestra menos de 50 compilaciones / seg y menos de 15 recompilaciones / seg.
Después de ejecutar una sesión XE en busca de compilaciones, estamos viendo miles de compilaciones por segundo.
Este sistema está utilizando disparadores para auditar los cambios. La mayoría de las compilaciones se deben a desencadenantes. Los desencadenantes hacen referencia a sys.dm_tran_active_transactions.
Nuestro primer pensamiento fue que tal vez hacer referencia a un DMV en un disparador haría que se compilara cada vez, o tal vez solo este DMV específico lo causaría. Entonces comencé a probar esa teoría. Se compila cada vez, pero no había comprobado si un disparador se compila cada vez que se dispara cuando no hace referencia al DMV y en su lugar codifica un valor. Todavía se estaba compilando cada vez que se activaba. Al soltar el gatillo se detienen las compilaciones.
- Estamos utilizando sqlserver.query_pre_execution_showplan en una sesión XE para rastrear las compilaciones. ¿Por qué hay una discrepancia entre eso y el contador PerfMon?
- ¿Es normal que obtenga un evento de compilación cada vez que se ejecuta un disparador?
Repro script:
CREATE TABLE t1 (transaction_id int, Column2 varchar(100));
CREATE TABLE t2 (Column1 varchar(max), Column2 varchar(100));
GO
CREATE TRIGGER t2_ins
ON t2
AFTER INSERT
AS
INSERT INTO t1
SELECT (SELECT TOP 1 transaction_id FROM sys.dm_tran_active_transactions), Column2
FROM inserted;
GO
--Both of these show compilation events
INSERT INTO t2 VALUES ('row1', 'value1');
INSERT INTO t2 VALUES ('row2', 'value2');
GO
ALTER TRIGGER t2_ins
ON t2
AFTER INSERT
AS
INSERT INTO t1
SELECT 1000, Column2
FROM inserted;
GO
--Both of these show compilation events
INSERT INTO t2 VALUES ('row3', 'value3');
INSERT INTO t2 VALUES ('row4', 'value4');
DROP TRIGGER t2_ins;
--These do not show compilation events
INSERT INTO t2 VALUES ('row5', 'value5');
INSERT INTO t2 VALUES ('row6', 'value6');
DROP TABLE t1, t2;
fuente
No. Los disparadores no siempre se vuelven a compilar. Sin embargo, las declaraciones de consulta simples no almacenan en caché sus planes y, por lo tanto, siempre se vuelven a compilar.
Los disparadores se vuelven a compilar si el número de filas insertadas o eliminadas cambia significativamente. Ver: https://technet.microsoft.com/en-us/library/ms181055.aspx
No sé si tienen lo mismo en XEvents, pero en SQL Trace, una recompilación tiene una subclase de evento que le dice por qué se volvió a compilar. Eso se explica en el mismo enlace de arriba.
fuente