Sql中的WHERE,結合兩個快速條件會成倍增加成本 (WHERE in Sql, combining two fast conditions multiplies costs many times)


問題描述

Sql中的WHERE,結合兩個快速條件會成倍增加成本 (WHERE in Sql, combining two fast conditions multiplies costs many times)

I have a fairly complex sql that returns 2158 rows' id from a table with ~14M rows. I'm using CTEs for simplification. 

The WHERE consists of two conditions. If i comment out one of them, the other runs in ~2 second. If i leave them both (separated by OR) the query runs ~100 seconds. The first condition alone needs 1‑2 seconds and returns 19 rows, the second condition alone needs 0 seconds and returns 2139 rows.

What can be the reason?

This is the complete 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 

Here's the execution plan:

Download: http://www.filedropper.com/exeplanfpc

‑‑‑‑‑

參考解法

方法 1:

Try to use UNION ALL of 2 queries separately instead of OR condition. 

I've tried it many times and it really helped. I've read about this issue in Art Of SQL .

Read it, you can find many useful information about performance issues. 

UPDATE: 

Check related questions

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?

Check Wes's answer 

  

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

(by Tim Schmelterhgulyan)

參考文件

  1. WHERE in Sql, combining two fast conditions multiplies costs many times (CC BY‑SA 3.0/4.0)

#sql-server-2005 #performance #SQL #tsql






相關問題

可更新查詢所需的最低權限 (Access Project) (Minimum permissions required for an updatable query (Access Project))

Sql中的WHERE,結合兩個快速條件會成倍增加成本 (WHERE in Sql, combining two fast conditions multiplies costs many times)

是否可以重構此語句以刪除子查詢? (Is it possible to refactor this statement to remove the subquery?)

Không gửi được tệp nhật ký bằng 'Tác vụ Gửi Thư' từ trình xử lý OnError (Sending the log file using a 'Send Mail Task' from the OnError handler fails)

擴展 SSRS 中的圖表功能 (Extending chart functionality in SSRS)

sql server 2005 數據庫郵件錯誤(操作已超時) (sql server 2005 database mail error (The operation has timed out))

從.NET應用程序到SQL Server的緩慢調用 (Sporadically Slow Calls From .NET Application To SQL Server)

我需要在 sql 中獲取 alldata whereclause? (i need to get alldata whereclause in sql?)

一種檢查 SQL 2005 中是否存在外鍵的方法 (A way to check if foreign key exists in SQL 2005)

如何在 SSIS 中調用存儲過程? (How do you call a Stored Procedure in SSIS?)

什麼會使桌子“變慢”? (What would make a table "slow?")

可以在這裡使用 Common Table 表達式來提高性能嗎? (Can Common Table expressions be used here for performance?)







留言討論