我们正在对 CPU 利用率高的服务器进行故障排除。在发现查询并没有真正导致它之后,我们开始研究编译。
性能监视器显示低于 50 次编译/秒和低于 15 次重新编译/秒。
在运行 XE 会话以查找编译后,我们看到每秒有数千次编译。
该系统使用触发器来审核更改。大多数编译是由于触发器。触发器引用 sys.dm_tran_active_transactions。
我们的第一个想法是,也许在触发器中引用 DMV 会导致它每次都编译,或者可能只是这个特定的 DMV 会导致它。所以我开始测试这个理论。它每次都编译,但我没有检查触发器是否在每次触发时编译,当它不引用 DMV 而是硬编码一个值时。每次触发时它仍在编译。删除触发器会停止编译。
- 我们在 XE 会话中使用 sqlserver.query_pre_execution_showplan 来跟踪编译。为什么这与 PerfMon 计数器之间存在差异?
- 每次触发器运行时都会收到编译事件是否正常?
复制脚本:
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;