Estamos solucionando um servidor que tem alta utilização da CPU. Depois de descobrir que as consultas não estavam causando isso, começamos a procurar compilações.
O Monitor de desempenho está mostrando menos de 50 compilações/s e menos de 15 recompilações/s.
Depois de executar uma sessão XE procurando por compilações, estamos vendo milhares de compilações por segundo.
Este sistema está usando gatilhos para auditar mudanças. A maioria das compilações são devido a gatilhos. Os gatilhos fazem referência a sys.dm_tran_active_transactions.
Nosso primeiro pensamento foi que talvez referenciar um DMV em um gatilho faria com que ele compilasse todas as vezes, ou talvez apenas esse DMV específico o causasse. Então comecei a testar essa teoria. Ele compila toda vez, mas eu não verifiquei se um gatilho compila toda vez que é acionado quando não faz referência ao DMV e, em vez disso, codifica um valor. Ele 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ê receba um evento de compilação toda vez que um gatilho é executado?
Reproduzir 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;