2017-04-07 127 views
-1

这是在Windows SQL Server群集上。Microsoft SQL Server:错误的查询执行计划耗时太长

查询来自第三方应用程序,所以我无法永久修改查询。

查询:

DECLARE @FromBrCode INT = 1001 
DECLARE @ToBrCode INT = 1637 
DECLARE @Cdate DATE = '31-mar-2017' 

SELECT 
    a.PrdCd, a.Name, SUM(b.Balance4) as Balance 
FROM 
    D009021 a, D010014 b 
WHERE 
    a.PrdCd = LTRIM(RTRIM(SUBSTRING(b.PrdAcctId, 1, 8))) 
    AND substring(b.PrdAcctId, 9, 24) = '000000000000000000000000' 
    AND a.LBrCode = b.LBrCode 
    AND a.LBrCode BETWEEN @FromBrCode AND @ToBrCode 
    AND b.CblDate = (SELECT MAX(c.CblDate) 
        FROM D010014 c 
        WHERE c.PrdAcctId = b.PrdAcctId 
         AND c.LBrCode = b.LBrCode 
         AND c.CblDate <= @Cdate) 
GROUP BY 
    a.PrdCd, a.Name 
HAVING 
    SUM(b.Balance4) <> 0 
ORDER BY 
    a.PrdCd 

这种特殊的查询花费太多的时间来完成执行。同一个问题发生在不同的SQL Server上。

没有发现表锁,查询运行时处理器和内存使用情况正常。

正常“选择顶1000”两个表中所做的工作,并表示这两个表(D009021,D​​010014)

重新编制在瞬间输出和重建/更新统计数据,但问题并没有解决(D009021,D​​010014)

同样的查询工作,如果我们减少分支的数量,但慢慢地

(
    DECLARE @FromBrCode INT =1001 
    DECLARE @ToBrCode INT =1001 
    ) 

同样的查询工作更快给予2分钟内输出,如果我们更换任何一个变量,直接使用值

AND a.LBrCode BETWEEN @FromBrCode AND @ToBrCode 

改为

AND a.LBrCode BETWEEN 1001 AND @ToBrCode 

同样的查询工作更快,2分钟内让输出,如果我们在结尾处添加“选项(重新编译)”

我试图清理缓存查询执行计划并优化新的但问题仍然存在

发现查询估计计划和实际执行计划不同(请参见屏幕截图)

working plan long waiting plan

+3

你为什么不只是让'OPTION(RECOMPILE)'永久的吗?对于可能看到参数值的选择性差异很大的查询,没有任何问题。 –

+2

另外,您最后一次重建统计信息的时间是?或者这就是你在步骤5中“重建”的含义? –

+0

该查询来自另一个应用程序,我不能修改。重建/更新统计信息没有解决问题 – Sumanta

回答

0

表D010014的别名一次为b的两倍,并且一旦为c 的它们连接到相同的表。 请尝试删除下面的子查询并创建一个临时表来存储您需要的值 。我加*你自己加入

SELECT MAX(c.CblDate) 领域FROM D010014Ç WHERE c.PrdAcctId = b.PrdAcctIdc.LBrCode = b.LBrCode 和C. CblDate < = @Cdate

如果你不能这样做,那么尝试

SELECT TOP 1 c.CblDate 
        FROM D010014 c 
        WHERE c.PrdAcctId = b.PrdAcctId 
         AND c.LBrCode = b.LBrCode 
         AND c.CblDate <= @Cdate 
         ORDER BY c.CblDate DESC 
+0

谢谢,但正如我前面所说“查询来自第三方应用程序,所以我不能修改查询永久。” – Sumanta

+0

您是否允许对表格上的索引进行分区,或者创建新的索引?如果没有玩过像KEEP PLAN或KEEPFIXED PLAN这样的提示,至少可以估计更接近实际的计划。 – Cooker