sql - Sql中的WHERE,组合两个快速条件会使成本成倍增加

标签 sql performance t-sql sql-server-2005

我有一个相当复杂的 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 ALL 而不是 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?

查看韦斯的回答

The usage of the OR is probably causing the query optimizer to no longer use an index in the second query.

关于sql - Sql中的WHERE,组合两个快速条件会使成本成倍增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12091019/

相关文章:

mysql - 最好是在 InnoDB 主键末尾插入,还是分散插入?

sql - 删除表中记录数给定的记录数

sql - 与稍后提供的一起加入

sql - 如何在 SQL Server 中备份对称 key ?

mysql - SQL的1=1子句的解释

wcf - 使用netTcpBinding调整WCF的性能

sql - 使用 SQL 将行转换为列

php - MySQL : complex query dynamic select?

sql - 从双选择中选择的 where 子句中的错误 PL/SQL 查询

python - 加速将概率转化为二进制特征