Wir suchen nach einem Server mit hoher CPU-Auslastung. Nachdem wir festgestellt hatten, dass die Abfragen dies nicht wirklich verursachten, begannen wir, Kompilierungen zu untersuchen.
Der Systemmonitor zeigt weniger als 50 Kompilierungen pro Sekunde und weniger als 15 Kompilierungen pro Sekunde an.
Nach dem Ausführen einer XE-Sitzung, in der nach Kompilierungen gesucht wird, werden Tausende von Kompilierungen pro Sekunde angezeigt.
Dieses System verwendet Trigger, um Änderungen zu überwachen. Die meisten Kompilierungen sind auf Trigger zurückzuführen. Der Trigger verweist auf sys.dm_tran_active_transactions.
Unser erster Gedanke war, dass ein Verweis auf eine DMV in einem Trigger dazu führen könnte, dass sie jedes Mal kompiliert wird, oder dass dies möglicherweise nur durch diese spezifische DMV verursacht wird. Also fing ich an, diese Theorie zu testen. Es wird jedes Mal kompiliert, aber ich hatte nicht geprüft, ob ein Trigger jedes Mal kompiliert wird, wenn er nicht auf die DMV verweist und stattdessen einen Wert fest codiert. Es wurde immer noch jedes Mal kompiliert, wenn es ausgelöst wurde. Durch das Löschen des Auslösers werden die Kompilierungen gestoppt.
- Wir verwenden sqlserver.query_pre_execution_showplan in einer XE-Sitzung, um die Kompilierungen zu verfolgen. Warum besteht eine Diskrepanz zwischen diesem und dem PerfMon-Zähler?
- Ist es normal, dass Sie jedes Mal, wenn ein Trigger ausgeführt wird, ein Kompilierungsereignis erhalten?
Repro-Skript:
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;
quelle
Trigger werden nicht immer neu kompiliert. Einfache Abfrageanweisungen werden jedoch nicht zwischengespeichert und werden daher immer neu kompiliert.
Trigger werden neu kompiliert, wenn sich die Anzahl der eingefügten oder gelöschten Zeilen erheblich ändert. Siehe: https://technet.microsoft.com/en-us/library/ms181055.aspx
Ich weiß nicht, ob sie in XEvents identisch sind, aber in SQL Trace verfügt eine Neukompilierung über eine Ereignisunterklasse, die angibt, warum sie neu kompiliert wurde. Das wird im selben Link oben erklärt.
quelle