Мы устраняем неполадки на сервере с высокой загрузкой ЦП. Обнаружив, что запросы на самом деле не вызывают его, мы начали изучать компиляции.
Монитор производительности показывает менее 50 компиляций в секунду и менее 15 перекомпиляций в секунду.
После запуска сеанса XE в поисках компиляций мы видим тысячи компиляций в секунду.
Эта система использует триггеры для аудита изменений. Большинство сборников происходит из-за триггеров. Триггеры ссылаются на sys.dm_tran_active_transactions.
Нашей первой мыслью было, что, возможно, ссылка на DMV в триггере вызовет его компиляцию каждый раз, или, может быть, именно этот конкретный DMV вызовет его. Поэтому я начал проверять эту теорию. Он компилируется каждый раз, но я не проверял, компилируется ли триггер каждый раз, когда он срабатывает, когда не ссылается на DMV и вместо этого жестко кодирует значение. Он все еще компилировался каждый раз, когда срабатывал. Сброс триггера останавливает компиляцию.
- Мы используем sqlserver.query_pre_execution_showplan в сеансе XE для отслеживания компиляций. Почему существует несоответствие между этим и счетчиком PerfMon?
- Это нормально, что вы получаете событие компиляции каждый раз, когда запускается триггер?
Repro скрипт:
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;