Ми усуваємо проблеми з сервером, який використовує центральний процесор. Виявивши, що запити насправді не викликають цього, ми почали розглядати компіляції.
Монітор продуктивності показує менше 50 компіляцій в секунду і менше 15 репіляцій / сек.
Після запуску сеансу XE, який шукає компіляції, ми бачимо тисячі компіляцій в секунду.
Ця система використовує тригери для аудиту змін. Більшість компіляцій відбувається через тригери. Тригери посилаються на sys.dm_tran_active_transaction.
Наша перша думка полягала в тому, що, можливо, посилання 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;