【发布时间】: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 步中的“重建”?
-
该查询来自另一个我无法修改的应用程序。重建/更新统计信息并没有解决问题
-
会不会是参数嗅探问题?看到这个问题。 stackoverflow.com/questions/30061405/parameter-sniffing
-
告诉销售该软件的第三方:Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 proper i> ANSI-92 SQL 标准(25 年前 前)中的 ANSI
JOIN语法,不鼓励使用
标签: sql-server sql-server-2008