Microsoft SQL Server:错误的查询执行计划耗时过长

Posted

技术标签:

【中文标题】Microsoft SQL Server:错误的查询执行计划耗时过长【英文标题】:Microsoft SQL Server: wrong query execution plan taking too long 【发布时间】:2017-04-07 01:15:45 【问题描述】:

这是在 Windows SQL Server 集群上。

查询来自第 3 方应用程序,因此我无法永久修改查询。

查询是:

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、D010014)

重新索引和重建/更新两个表中的统计信息,但问题没有解决(D009021、D010014)

如果我们减少分支数量但缓慢,则相同的查询会起作用

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

如果我们替换任何一个变量并直接使用该值,相同的查询会在 2 分钟内更快地给出输出

 AND a.LBrCode BETWEEN @FromBrCode AND @ToBrCode

改为

AND a.LBrCode BETWEEN 1001 AND @ToBrCode

如果我们在末尾添加“OPTION (RECOMPILE)”,相同的查询会运行得更快并在 2 分钟内给出输出

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

发现查询估计计划和实际执行计划不一样(见截图)

【问题讨论】:

你为什么不把OPTION (RECOMPILE)永久化?对于可能会看到具有广泛不同选择性的参数值的查询,这并没有错。 另外,您上次重建统计数据是什么时候?或者这就是您所说的第 5 步中的“重建”? 该查询来自另一个我无法修改的应用程序。重建/更新统计信息并没有解决问题 会不会是参数嗅探问题?看到这个问题。 ***.com/questions/30061405/parameter-sniffing 告诉销售该软件的第三方:Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 proper i> ANSI-92 SQL 标准(25 年前 前)中的 ANSI JOIN 语法,不鼓励使用 【参考方案1】:

表 D010014 有两次别名,一次为 b,一次为 c 它们连接到同一张表。 尝试删除下面的子查询并创建一个临时表来存储 您需要的值。我在您自己加入的字段中添加了 *

选择最大值(c.CblDate) 从 D010014 c WHERE c.PrdAcctId = b.PrdAcctId AND c.LBrCode = b.LBrCode AND c.CblDate

如果你做不到,那就试试

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

【讨论】:

谢谢,但正如我之前所说的“查询来自第 3 方应用程序,因此我无法永久修改查询。” 是否允许对表上的索引进行分区,或者创建新索引?如果不使用 KEEP PLAN 或 KEEPFIXED PLAN 之类的提示,至少可能会更接近估计和实际计划。

以上是关于Microsoft SQL Server:错误的查询执行计划耗时过长的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft SQL Server,错误: 3702

Microsoft SQL Server,错误: 3702

PCB MS SQL SERVER 字段含小写字母更新为大写字母

Microsoft SQL Server,错误: 18456

连接失败: SQLState:'01000' SQL Server 错误: 53 [Microsoft][ODBC SQL Server Driver][DBNETLIB]Connec

sql2000安装失败,错误提示([Microsoft][ODBC SQL Server Driver][Shared Memory]SQL Server 不存在或?)