Sql中的WHERE,结合两个快速条件会成倍增加成本
Posted
技术标签:
【中文标题】Sql中的WHERE,结合两个快速条件会成倍增加成本【英文标题】:WHERE in Sql, combining two fast conditions multiplies costs many times 【发布时间】:2012-08-18 22:23:25 【问题描述】:我有一个相当复杂的 sql,它从大约 14M 行的表中返回 2158 行的 id。我正在使用 CTE 进行简化。
WHERE
包含两个条件。如果我注释掉其中一个,另一个会在大约 2 秒内运行。如果我将它们都保留(由OR
分隔),则查询运行约 100 秒。单独第一个条件需要1-2秒,返回19行,单独第二个条件需要0秒,返回2139行。
可能是什么原因?
这是完整的 SQL:
WITH fpcRepairs AS
(
SELECT FPC_Row = ROW_NUMBER()OVER(PARTITION BY t.SSN_Number ORDER BY t.Received_Date, t.Claim_Creation_Date, t.Repair_Completion_Date, t.Claim_Submitted_Date)
, idData, Repair_Completion_Date, Received_Date, Work_Order, SSN_number, fiMaxActionCode, idModel,ModelName
, SP=(SELECT TOP 1 Reused_Indicator FROM tabDataDetail td INNER JOIN tabSparePart sp ON td.fiSparePart=sp.idSparePart
WHERE td.fiData=t.idData
AND (td.Material_Quantity <> 0)
AND (sp.SparePartName = '1254-3751'))
FROM tabData AS t INNER JOIN
modModel AS m ON t.fiModel = m.idModel
WHERE (m.ModelName = 'LT26i')
AND EXISTS(
SELECT NULL
FROM tabDataDetail AS td
INNER JOIN tabSparePart AS sp ON td.fiSparePart = sp.idSparePart
WHERE (td.fiData = t.idData)
AND (td.Material_Quantity <> 0)
AND (sp.SparePartName = '1254-3751')
)
), needToChange AS
(
SELECT idData FROM tabData AS t INNER JOIN
modModel AS m ON t.fiModel = m.idModel
WHERE (m.ModelName = 'LT26i')
AND EXISTS(
SELECT NULL
FROM tabDataDetail AS td
INNER JOIN tabSparePart AS sp ON td.fiSparePart = sp.idSparePart
WHERE (td.fiData = t.idData)
AND (td.Material_Quantity <> 0)
AND (sp.SparePartName IN ('1257-2741','1257-2742','1248-2338','1254-7035','1248-2345','1254-7042'))
)
)
SELECT t.idData
FROM tabData AS t INNER JOIN modModel AS m ON t.fiModel = m.idModel
INNER JOIN needToChange ON t.idData = needToChange.idData -- needs to change FpcAssy
LEFT OUTER JOIN fpcRepairs rep ON t.idData = rep.idData
WHERE
rep.idData IS NOT NULL -- FpcAssy replaced, check if reused was claimed correctly
AND rep.FPC_Row > 1 -- other FpcAssy repair before
AND (
SELECT SP FROM fpcRepairs lastRep
WHERE lastRep.SSN_Number = rep.SSN_Number
AND lastRep.FPC_Row = rep.FPC_Row - 1
) = rep.SP -- same SP, must be rejected(reused+reused or new+new)
OR
rep.idData IS NOT NULL -- FpcAssy replaced, check if reused was claimed correctly
AND rep.FPC_Row = 1 -- no other FpcAssy repair before
AND rep.SP = 0 -- not reused, must be rejected
order by t.idData
这是执行计划:
下载:http://www.filedropper.com/exeplanfpc
【问题讨论】:
您是否尝试分别使用 2 个查询的 UNION 而不是 OR 条件? @hgulyan:如果您将其发布为答案,我至少会支持它。使用UNION ALL
只需 3 秒。为什么?
好的,谢谢。我只是不确定是不是你的情况。也试试 UNION,而不是 UNION ALL :)
@hgulyan:我为什么要使用UNION
? UNION ALL
更快,两个条件互斥(FPC_Row = 1 和 FPC_Row > 1)。
@TimSchmelter - 回复:为什么?见***.com/q/5901791/73226
【参考方案1】:
尝试分别使用 UNION ALL 的 2 个查询,而不是 OR 条件。
我已经尝试了很多次,它确实很有帮助。我在Art Of SQL 中读到过这个问题。
阅读它,您可以找到许多有关性能问题的有用信息。
更新:
检查相关问题
UNION ALL vs OR condition in sql server query
http://www.sql-server-performance.com/2011/union-or-sql-server-queries/
Can UNION ALL be faster than JOINs or do my JOINs just suck?
查看韦斯的答案
OR 的使用可能导致查询优化器在第二个查询中不再使用索引。
【讨论】:
以上是关于Sql中的WHERE,结合两个快速条件会成倍增加成本的主要内容,如果未能解决你的问题,请参考以下文章
如何比较 SQL where 条件中的两个逻辑表达式? [关闭]