不能用触发器捕获执行计划异常,因为触发器不参与查询编译与执行阶段,无法访问query_plan_hash、plan_handle或动态管理视图中的计划信息;唯一可行路径是扩展事件(如query_post_execution_showplan)。

不能用触发器捕获执行计划异常——DDL 或 DML 触发器都不行。 这不是配置问题,而是 SQL Server 的执行机制决定的:触发器只响应结构变更(如 CREATE_PROCEDURE)或数据变更(如 INSERT),它完全不参与查询编译、计划生成或执行阶段,更拿不到 query_plan_hash 或 plan_handle。
为什么 DDL 触发器对执行计划完全无效
DDL 触发器只监听 CREATE、ALTER、DROP 等语句,而执行计划是在 EXEC、sp_executesql 或 DML 语句实际运行时才生成并缓存的。即使你对某个存储过程建了 CREATE_PROCEDURE 触发器,它也只能在过程被创建/修改时触发一次,之后该过程每次执行,触发器都毫无反应。
-
sys.dm_exec_query_plan和sys.dm_exec_cached_plans中的计划数据,触发器内部根本无法访问 - 试图在触发器里查
sys.dm_exec_requests或sys.dm_exec_sessions只能得到当前会话的粗粒度状态,没有计划树、没有警告图标、没有 missing index 提示 - 加密存储过程(
WITH ENCRYPTION)不影响运行时计划暴露,但触发器依然抓不到——因为不是权限问题,是时机问题
真正能拿到执行计划异常的唯一路径:扩展事件(XEvent)
SQL Server 2017 支持 query_post_execution_showplan 事件,它在语句执行完毕后把完整 XML 执行计划推送到事件会话中。但注意:它不区分“异常”,而是捕获所有满足条件的计划——你要靠后续分析识别低效模式(如表扫描、并行阈值超限、内存授予不足警告)。
- 必须显式开启
SHOWPLAN权限:GRANT SHOWPLAN TO [user] - 仅建议短时启用,因每个计划 XML 平均占用 50–200 KB 内存,高并发下极易拖慢服务器
- 生产环境更推荐组合使用:
rpc_completed+sql_batch_completed,再通过plan_handle关联查sys.dm_exec_query_plan(plan_handle) - 查计划必须“立即”执行——延迟几秒再查
sys.dm_exec_query_plan,可能因内存压力导致计划已被驱逐,返回NULL
想定位触发器自身引起的性能异常?别用触发器追踪自己
如果你怀疑某个 AFTER INSERT 触发器变慢,直接在 SSMS 中用 SET STATISTICS XML ON 执行等效逻辑(模拟 inserted 表内容),看执行计划里是否有全表扫描、嵌套循环放大、标量函数调用等红标警告。
- 不要依赖 SQL Server Profiler:它默认过滤掉触发器内语句,除非手动勾选
SP:StmtCompleted并取消 “仅收集客户端 API 调用” - 用扩展事件替代 Profiler:创建会话捕获
sp_statement_completed,加WHERE object_type = 'TR'过滤,避免日志爆炸 - 检查
sys.dm_exec_trigger_stats,它直接提供每个触发器的累计执行次数、平均耗时、最大逻辑读——比从头解析事件快得多
真正难的不是“怎么抓”,而是“抓完怎么筛”。执行计划 XML 里埋着几十个节点,Warnings、RelOp、QueryPlan 下的属性才是关键线索;而这些,任何触发器都碰不到边界。

















