Estamos solucionando problemas de um servidor com alta utilização da CPU. Depois de descobrir que as consultas não estavam realmente causando isso, começamos a procurar compilações.
O Monitor de desempenho está exibindo menos de 50 compilações / s e menos de 15 recompilações / s.
Depois de executar uma sessão XE procurando compilações, estamos vendo milhares de compilações por segundo.
Este sistema está usando gatilhos para auditar alterações. A maioria das compilações ocorre devido a gatilhos. Os gatilhos referenciam sys.dm_tran_active_transactions.
Nosso primeiro pensamento foi que talvez fazer referência a um DMV em um gatilho fizesse com que ele fosse compilado a cada vez, ou talvez apenas esse DMV específico o causasse. Então eu comecei a testar essa teoria. Ele é compilado toda vez, mas eu não tinha verificado se um gatilho é compilado toda vez que é acionado quando não faz referência à DMV e, em vez disso, codifica um valor. Ainda estava compilando cada vez que era acionado. Soltar o gatilho interrompe as compilações.
- Estamos usando sqlserver.query_pre_execution_showplan em uma sessão XE para rastrear as compilações. Por que há uma discrepância entre isso e o contador PerfMon?
- É normal que você obtenha um evento de compilação cada vez que um gatilho é executado?
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;