【问题标题】:MS SQL Query changed plan and became incredibly slowMS SQL Query 改变了计划,变得异常缓慢
【发布时间】:2017-10-24 17:11:17
【问题描述】:

我们有一个查询已经运行了 3 年以上,没有任何问题。

查询是来自我们的 ERP 系统 (Microsoft Dynamics AX) 的标准查询,如下所示:

SELECT SUM(B.COSTAMOUNTPOSTED),SUM(B.QTY) FROM INVENTTRANSPOSTING A,INVENTTRANS B 
WHERE ((A.DATAAREAID=N'01') AND (((A.ITEMID=@P1) AND (A.INVENTTRANSPOSTINGTYPE=@P2)) AND (A.TRANSDATE>@P3))) 
AND ((B.DATAAREAID=N'01') AND ((((B.VOUCHER=A.VOUCHER) AND (B.DATEFINANCIAL=A.TRANSDATE)) 
AND (B.INVENTTRANSID=A.INVENTTRANSID)) AND (B.PACKINGSLIPRETURNED=@P4))) 
AND EXISTS (SELECT 'x' FROM INVENTDIM C WHERE ((C.DATAAREAID=N'01') AND ((((((((((C.INVENTDIMID=B.INVENTDIMID) AND (C.CONFIGID=@P5)) AND (C.INVENTSIZEID=@P6)) AND (C.INVENTCOLORID=@P7)) AND (C.INVENTSITEID=@P8)) AND (C.INVENTLOCATIONID=@P9)) AND (C.INVENTBATCHID=@P10)) AND (C.WMSLOCATIONID=@P11)) AND (C.WMSPALLETID=@P12)) AND (C.INVENTSERIALID=@P13)))

或者以更易读的形式:

select TableId from inventTransPosting           
        where inventTransPosting.ItemId                 == itemId                            &&
              inventTransPosting.InventTransPostingType == InventTransPostingType::Financial &&
              inventTransPosting.TransDate              >  perDate
    join sum(CostAmountPosted),sum(Qty) from inventTrans            
        where inventTrans.Voucher                       == inventTransPosting.Voucher        &&
              inventTrans.DateFinancial                 == inventTransPosting.TransDate      &&
              inventTrans.InventTransId                 == inventTransPosting.InventTransId  &&
              inventTrans.PackingSlipReturned           == NoYes::No
    exists join inventDim   
        where inventDim.inventDimId == inventTrans.inventDimId &&
              inventDim.configId    == configId &&
              inventDim.inventColorId == inventColorId;

现在这个查询突然改变了它的执行计划,从几毫秒的执行到单次运行需要 10 到 20 分钟。

我尝试重新索引查询中涉及的所有 3 个表,但没有成功。

如果我查看查询计划,我发现索引查找已成为键查找,但查询、索引或表中没有任何变化!

为什么会这样?

这是一切正常时的查询计划:

这是现在的计划:

会是什么?

【问题讨论】:

  • 尝试粘贴实际的执行计划here,这样我们就可以从估计的计划中获得更多关于您的查询的信息。
  • 解决方法是使用 sp_create_plan_guide 来强制执行所需的计划 (technet.microsoft.com/en-us/library/ms179880(v=sql.105).aspx)。您运行的 SQL Server 版本是什么?
  • @RigertaDemiri 很抱歉,您提供的 URL 不起作用,因为查询包含不受支持的 StmtCursor。我们注意到您的计划正在使用光标 (StmtCursor)。不幸的是,粘贴计划还没有显示带有光标的计划。你现在可以翻转桌子了。 (╯°□°)╯︵┻━┻
  • @DeanSavović 我更想了解为什么会发生这种情况,sp_create_plan_guide 对我来说似乎是一个临时工作。没那么优雅..
  • @Jason 是的,表格和统计信息已在 3 天前更新(今天也是,因为我对 3 个表格做了 dbcc dbreindex)

标签: sql sql-server performance sql-server-2008


【解决方案1】:

如 cmets 中所述,优化器可能正在估计小的基数并仅使用嵌套循环。

由于我无法编辑添加重新编译的查询文本,使用索引或其他方式(查询是直接从 ERP 创建的)解决问题的独特方法是:

plan_guide 重构查询

我决定选择后者。我已经拆分了删除连接的查询,现在它工作正常。 (即使这不是最佳解决方案。我不喜欢 MS SQL 在这里的工作方式)

【讨论】:

  • 如果重新启动/更新 SQL Server 是一个选项,还需要考虑 trace flag 4199。从 SQL Server 2017 开始,引擎有一个built in feature 来防止这种计划回归。
  • @JeroenMostert 感谢您的提示,了解自动调优和 SQL 计划选择回归很有用。如果我们将切换到 mssql 2017,我会记住这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多