我有两个表(Table1, Table2),并且来自Table1的Id是Table2中的外键。两个表都有删除更新其他表的触发器(表3)。表1上的Delete级联表2上的Delete。当我执行
delete from Table1
where Table4Id = @table4Id
i'am getting compilation timeout on Table2 trigger
SQL Server parse and compile time:
CPU time = 391 ms, elapsed time = 10726 ms.
StatementOptmEarlyAbortReason="TimeOut"
On delete trigger from Table1
UPDATE table3
SET table3.Column1 = NULL
FROM Table3 AS table3
JOIN DELETED AS deleted ON deleted.Table4Id = table3.Table4Id
WHERE deleted.Column1 = 1
On delete trigger from Table2
UPDATE table3
SET table3.Column1 = NULL
FROM Table1 AS table1
JOIN DELETED AS deleted on deleted.Table1Id = table1.Id
JOIN Table3 AS table3 ON deleted.Table3Id = table3.Id
WHERE table1.Column1 = 1 AND table1.Table4Id = table3.Table4Id
是否有办法摆脱这个编译超时?
是否有办法摆脱这个编译超时?
这不是一个问题,这已经被Benjamin Nevarej描述在这里:查询优化的阶段
Query Optimizer是一个基于成本的优化器,当我们呈现一个查询时,它可以根据查询的复杂性经历不同的阶段。这些阶段是
阶段0—事务处理
阶段1—快速计划
阶段2—全面优化
还有一个叫做Timeout的阶段,下面是超时阶段
的解释DMV还可以显示超时事件。当发现超时时,Query Optimizer会停止优化过程,并返回迄今为止找到的成本最低的计划。此超时事件也显示在图形计划的属性上,作为语句优化的Reason For Early Termination of Statement Optimization,或显示在XML计划上,作为StatementOptmEarlyAbortReason。
您也可以使用DMV下方查看所有阶段
sys.dm_exec_query_optimizer_info
Paul White在他的博客中也证实了这一点。
优化器还在阶段开始时为它认为足以找到一个相当好的计划的优化"移动"数量设置预算(记住优化器的目标是快速找到一个足够好的计划)。如果在一个阶段中探索和实施替代方案的过程超出了这个"预算",则该阶段将以"超时"消息结束。提前终止(无论出于什么原因)是优化器设计的一部分,完全正常,通常不会引起关注。
进一步阅读. .
Query Optimizer Deep Dive系列by Paul white
由于我们的级联删除,您有两个触发器在同一时间更新同一表的同一记录中的同一列。它们都想要锁定它,但必须等待另一个,这会给你一个超时。
级联删除从来都不是一个好主意,更好的方法是为table1上的删除编写一个而不是触发器,它可以删除table2中的子记录并执行所需的所有日志记录。