代码之家  ›  专栏  ›  技术社区  ›  MatBailie

MS SQL Server 2005-存储过程“自动中断”

  •  8
  • MatBailie  · 技术社区  · 16 年前

    客户机报告了在执行存储过程时重复出现的非常奇怪的行为。

    它们的代码运行于易失性数据集的缓存转置。在以下情况下,写入存储过程以按需重新处理数据集:
    1.自上次重新处理后,数据集已更改

    (第二个条件在更改期间停止大量重复的重新计算。)


    这在几周内运行良好,SP需要1-2秒来完成重新处理,并且只在需要时执行。然后

    • SP突然“停止工作”(它只是继续运行,再也没有返回)
    • 几天后,它又停止工作了
    • 然后有人说“我们以前见过,只需重新编译SP”
    • 在代码没有更改的情况下,我们重新编译了SP,它成功了
    • 几天后,它又停止工作了


    这已经重复了很多次。SP突然“停止工作”,不再返回,客户端超时。(我们尝试通过ManagementStudio运行它,并在15分钟后取消了查询。)

    然而,每次我们重新编译SP时,它都会突然再次工作。


    • 有人对如何克服它有什么建议吗?


    干杯


    编辑:

    • 从表x中读取“a”
    • 从表x中读取“b”
    • 如果(a<b)返回
    • 删除表_y
    • 插入到表中_y<3选择联合在一起>
    • 更新表x
    • 提交事务

    8 回复  |  直到 16 年前
        1
  •  3
  •   RBarryYoung    16 年前

    这是参数嗅探的足迹。是的,第一步是尝试重新编译,尽管它并不总是按照您在2005年希望的方式工作。

    更新: 无论如何,我都会在INSERT上尝试语句级重新编译,因为这可能是一个统计问题(哦,是的,请检查是否启用了自动统计更新)。

    如果这似乎不适合参数嗅探,那么比较实际的查询计划,从它正常工作到永远运行(如果无法获得实际的查询计划,请使用估计的计划,尽管实际的更好)。您正在查看计划是否更改。

        2
  •  3
  •   Cade Roux    16 年前

    我完全同意参数嗅探诊断。如果SP的输入参数在变化(或者即使没有变化),请确保使用局部变量将其屏蔽,并在SP中使用局部变量。

    您也可以使用 WITH RECOMPILE 如果集合正在更改,但查询计划不再有效。

    在SQL Server 2008中,您可以使用 OPTIMIZE FOR UNKNOWN

    另外,如果您的流程涉及填充一个表,然后在另一个操作中使用该表,我建议将该流程拆分为单独的SP并分别调用它们 . 我认为,当您填充一个表,然后使用该表的结果执行操作时,在流程开始时生成的计划有时可能非常糟糕(糟糕到无法完成)。因为在初始计划时,表与初始插入后的表有很大不同。

        3
  •  1
  •   Ed Harper    16 年前

    正如其他人所说,数据或源表统计信息的变化方式导致缓存的查询计划过时。

    WITH RECOMPILE 可能是最快的修复使用 SET STATISTICS TIME ON 找出重新编译的实际成本是多少,然后立即放弃。

    如果这仍然不是一个可接受的解决方案,那么最好的选择可能是尝试重构insert语句。

    你不说你是否在使用 UNION UNION ALL 在insert语句中。我见过 INSERT INTO 具有 生成一些奇怪的查询计划,特别是在SQL 2005的SP2之前版本上。

    • 拉杰提出的放弃和放弃的建议 使用重新创建目标表 SELECT INTO 这是一条路要走。

    • 您还可以尝试选择以下各项: 这三个源查询将被转换为它们自己的源查询 协会 一起插入。

    • 或者,您可以尝试 这些建议的组合- 把工会的结果放在一份报告中 临时桌 选择进入 然后从中插入目标 桌子

    我见过所有这些方法在类似场景中解决性能问题;测试将揭示你所拥有的数据中哪一个能给出最好的结果。

        4
  •  0
  •   Community Mohan Dere    9 年前

    显然,更改存储过程(通过重新编译)会更改导致锁定的环境。

    尝试按说明记录SP的进度 here here .

        5
  •  0
  •   Paddy    16 年前

    我同意上面在评论中给出的答案,这听起来像是一个未关闭的事务,特别是当您仍然能够从查询分析器运行select语句时。

    听起来很像是有一个打开的事务,表_y有一个挂起的删除,此时无法插入。

    SP锁定时,是否可以执行表y的插入?

        6
  •  0
  •   Mitch Wheat    16 年前

    你有索引维护工作吗?

    你的统计数据是最新的吗?一种方法是检查估计的和实际的查询计划是否存在较大的差异。

        7
  •  0
  •   Jeff Meatball Yang    16 年前

    正如其他人所说,这听起来很可能是一个未提交的交易。

    我最好的猜测是:

    如果有其他存储过程或外部代码段在此表上保存事务,您可能会一直等待。(他们可能会出错,永远不会结束交易)

    另一个注意事项:如果可能,尝试使用truncate。它使用的资源少于不带where子句的delete:

    truncate table table_y
    

    begin tran
    begin try
     -- do normal stuff
    end try
    begin catch
     rollback
    end catch
    commit
    

    第一个错误将为您提供有关实际错误的信息。看到它挂在您自己的后续测试中只是一个次要影响。

        8
  •  0
  •   C B dkretz    8 年前

    如果您正在执行以下步骤:

    DELETE table_y
    INSERT INTO table_y <3 selects unioned together>
    

    你可能想试试这个

    DROP TABLE table_y
    SELECT INTO table_y <3 selects unioned together>