【问题标题】:MS SQL optimal execution plan compiling abort due time outMS SQL 最优执行计划编译中止到期超时
【发布时间】:2016-10-03 07:59:35
【问题描述】:

我有两个表(Table1、Table2),Table1 中的 Id 是 Table2 中的外键。两个表都在删除更新其他表(表 3)时触发。删除 Table1 级联删除 Table2。当我执行时

delete from Table1 
where  Table4Id = @table4Id

我在 Table2 触发器上遇到编译超时

SQL Server parse and compile time: 
    CPU time = 391 ms, elapsed time = 10726 ms.

StatementOptmEarlyAbortReason="TimeOut"

从 Table1 中删除触发器

UPDATE table3 
SET    table3.Column1 = NULL 
FROM Table3 AS table3
  JOIN DELETED AS deleted ON deleted.Table4Id = table3.Table4Id
WHERE deleted.Column1 = 1

从 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

有没有办法摆脱这个编译超时?

【问题讨论】:

  • 我猜这可能是因为你的级联删除你强制两个删除触发器在同一个事务中更新同一个表中的同一个字段。两个触发器都试图锁定它以更新它,但必须相互等待。
  • 执行删除语句不会编译任何东西。当您在“从 table1 中删除...”上按 F5 或在“创建触发器...”上按 F5 时是否会收到错误?
  • 当我在“从 Table1 中删除 ...”中按 F5 时出现此超时
  • 所以你在编译时不会出错,你没有编译任何东西
  • 您正在删除记录,而不是编译任何内容。级联表上的触发器正在触发,因为它们都试图锁定同一个表,所以你会超时。看我的回答,去掉触发器,去掉级联删除,在table1上创建一个instead of trigger

标签: sql-server timeout


【解决方案1】:

有没有办法摆脱这个编译超时?

这不是问题,Benjamin Nevarej 已在此处描述了这一点:The Phases of Query Optimization

查询优化器是一个基于成本的优化器,当我们提出一个查询时,它可以根据查询的复杂性经历不同的阶段。这些阶段是

阶段 0--事务处理
第一阶段——快速计划
第二阶段——全面优化

还有一个叫做超时的阶段,下面是超时阶段的解释

DMV 还可以显示超时事件。当发现超时时,查询优化器会停止优化过程并返回它迄今为止找到的最便宜的计划。此超时事件也显示在图形计划的属性中,作为提早终止语句优化的原因,或在 XML 计划中显示为 StatementOptmEarlyAbortReason。

您也可以使用下面的 DMV 查看所有阶段

sys.dm_exec_query_optimizer_info

Paul White 在他的博客中也证实了这一点..

优化器还在阶段开始时为它认为足以找到一个很好的计划的优化“移动”数量设置预算(请记住,优化器的目标是快速找到一个足够好的计划)。如果在某个阶段探索和实施替代方案的过程超出了此“预算”,则该阶段以“超时”消息结束。 提前终止(无论出于何种原因)是优化器设计的一部分,完全正常,通常无需担心

进一步阅读..

Query Optimizer Deep Dive Paul white 系列

【讨论】:

    【解决方案2】:

    由于我们的级联删除,您有 2 个触发器同时更新同一张表的同一记录中的同一列。他们每个人都想锁定它,但必须等待另一个,这会给你一个超时。

    级联删除从来都不是一个好主意,最好是在table1上写一个而不是触发器来删除,它可以删除table2中的子记录并完成所有需要的日志记录。

    【讨论】:

    • 我在编译期间超时。更新相同的记录不应该影响编译时间。
    • 然后更新您在编译期间收到错误的问题。您写道,执行此操作时出现错误:从 Table1 中删除,其中 Table4Id = @table4Id
    • 另外在哪个编译过程中你会得到错误?在 table1 的触发器上还是在 table2 的触发器上?或者别的地方 ?我在你的问题中看不到这一点
    • 这是 Table2 上的触发器
    • 您正在删除记录,而不是编译任何内容。级联表上的触发器正在触发,因为它们都试图锁定同一个表,所以你会超时。看我的回答,去掉触发器,去掉级联删除,在table1上创建一个instead of trigger
    猜你喜欢
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    相关资源
    最近更新 更多