【问题标题】:Known issue?: SQL Server 2005 stored procedure fails to complete with a parameter已知问题?:SQL Server 2005 存储过程无法通过参数完成
【发布时间】:2008-12-18 19:51:20
【问题描述】:

带有默认参数的基本 SP:

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID AS int = 20081130
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] WITH RECOMPILE
    */
    -- Stuff here that depends on DATA_DT_ID
END

具有硬编码本地的相同 SP。

ALTER PROCEDURE usp_debug_works]
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_works] WITH RECOMPILE
    */

    DECLARE @DATA_DT_ID AS int
    SET @DATA_DT_ID = 20081130
    -- Stuff here that depends on DATA_DT_ID
END

你可以看到我把(冗余,甚至)WITH RECOMPILE 选项放在哪里,以避免参数嗅探(这在开发中从来没有必要,因为这个东西运行良好)

一个可以在一两分钟内完成的工作,另一个永远不会完成 - 只是坐在那里几个小时。

开发服务器(build 9.00.3282.00)从来没有出现过这个问题,生产服务器是build 9.00.3068.00

我已经从 procs 中删除了各种代码,以尝试降低到仍然存在问题的最小版本,并且非常小心地保持 SP 的两个版本除了那个参数之外相同。

我有很多其他带有参数的 SP,它们运行良好。我还 DROPped 和 reCREATEed SP。

有什么想法吗?

是的,我有一个 DBA 正在查看它,但我没有 SHOWPLAN 或任何有用的生产权限来查看是否存在阻塞(如果一个人的计划导致锁升级,我猜 - 同样,唯一的区别是参数)

我已经查看了所有 SQL Server 构建信息,但没有发现与此相关的已知问题,所以在我弄清楚或 DBA 弄清楚之前,我有点卡住了。

更新

这也无法完成(这实际上是这些SP的正常形式-我只是放了一个默认值,以便在测试期间更容易来回切换)

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID AS int
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] 20081130 WITH RECOMPILE
    */
    -- Stuff here that depends on DATA_DT_ID
END

但是这个完成(这可能是一种解决方法,尽管我有大约 25 个这些 SP 需要修改,它们都具有相同的形式):

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID_in AS int
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] 20081130 WITH RECOMPILE
    */

    DECLARE @DATA_DT_ID AS int
    SET @DATA_DT_ID = @DATA_DT_ID_in
    -- Stuff here that depends on DATA_DT_ID
END

【问题讨论】:

  • 默认值是多少有关系吗?你能把代码去掉,然后一点一点地加回来,看看它什么时候被锁住了吗?

标签: sql sql-server sql-server-2005 stored-procedures


【解决方案1】:

尝试屏蔽输入参数。

我猜重新编译不起作用,因为指定的默认值(EDIT:或在第一次调用时发送的参数)在编译时被嗅探。所以,重新编译没有效果。

我已经看到估计计划之间的巨大差异,只需将默认值从零更改为 NULL,或者没有。

ALTER PROCEDURE [usp_debug_mightwork]
    @DATA_DT_ID AS int = 20081130
AS
BEGIN
    DECLARE @IDATA_DT_ID AS int
    SET @IDATA_DT_ID = @DATA_DT_ID
    -- Stuff here that depends on IDATA_DT_ID
END

我认为this article 解释...

...参数值在期间被嗅探 编译还是重新编译...

编辑:

New link on query plans and parameters。无论是否指定默认值,它仍然是参数嗅探。

上指定的 WITH RECOMPILE 选项 GetRecentSales 存储过程 以上不排除 基数估计误差

Kind of related article about constants and plans

【讨论】:

  • 参数屏蔽似乎有效。然而,默认值似乎不是主要原因 - 我已经用目前已知的内容更新了我的问题。
  • 这个问题可能只存在于某些版本中吗?它从未在开发中发生过。为什么不管选择 DATA_DT_ID 会产生如此巨大的差异(并且不完整),所有表中的基数都是相似的?为什么即使 SP 被丢弃。即它真的是 SQL Srv 中的错误吗?
  • 如果 SP 被丢弃,如果它正在使用,它可能不会被强制退出缓存。我找不到我的文章。第二个选项是由于负载差异,服务器上的统计信息或碎片可能会有所不同删除所有统计信息并重建所有索引,或者将 prod 恢复到 dev 并运行代码
  • 我经常看到 prod 与 dev 之间的差异,尽管所有机器都具有相同的操作系统和 SQL 构建以及相似的硬件规格。
  • DBA 带着同样的解决方案回来了——这是这个版本中的一个巨大错误,但这个版本已经过时了,所以无论如何,我猜。最终,如果需要这种级别的解决方法,客户端将无法维护该系统 - 他们不太了解 SQl Server。
【解决方案2】:

防止参数嗅探,否则当统计信息发生变化时您会吃不消。我有 500 多个 sps,所有这些都以:

DECLARE @_Param1 ..., @_ParamN

--- prevent pameter sniffing
SELECT @_Param1 = @Param1, @_ParamN = @ParamN

【讨论】:

  • 没关系,除了这是数据库中的一个新存储过程,所有参数值都具有相同的数据分布,而且这个过程不需要更长的时间——它永远不会完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 2014-05-16
  • 1970-01-01
  • 2023-03-20
  • 2010-12-04
  • 2011-11-07
相关资源
最近更新 更多