2012-09-14 128 views
1

我有一個動態查詢,可以識別成員還沒有租用的CD。我使用NOT IN子查詢,但是當我有大的成員表時,它會讓它們真的很慢。任何建議如何優化查詢NOT IN子查詢優化

SELECT DVDTitle AS "DVD Title" 
FROM DVD 
WHERE DVDId NOT IN 
    (SELECT DISTINCT DVDId FROM Rental WHERE MemberId = AL240); 

感謝

+2

哪些表定義,包括列的爲空和索引? –

+1

你有'Rental(MemberID,DVDId)'的索引嗎? –

+0

給了我們更多的信息,比如行數,索引等 –

回答

5

使用NOT EXISTS將有表現略好,因爲它可以「短路」,而不是評估每場比賽的整個集合。至少,它不會比NOT INOUTER JOIN「糟糕」,儘管每個規則都有例外。這是我會怎麼寫這個查詢:

SELECT DVDTitle AS [DVD Title] 
    FROM dbo.DVD AS d 
    WHERE NOT EXISTS 
    (
    SELECT 1 FROM dbo.Rental 
    WHERE MemberId = 'AL240' 
    AND DVDId = d.DVDId 
); 

我猜你會被調查的執行計劃,並確保您的索引是最適合這個查詢更好地優化性能(不會引起其他地區的負面影響您的工作量)。

另見Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?

+0

如果兩個'DVDId'列都不能爲空,我會期望'NOT IN'和'NOT EXISTS'具有相同的計劃。如果兩者都可以爲空,那麼'NOT IN'版本[需要做更多的工作](http://stackoverflow.com/a/11074428/73226) –

+0

@MartinSmith是的,這是真的,但請注意,我也消除了'DISTINCT ' –

+0

如果您不確定,只是默認爲不存在。它幾乎總是反連接的最佳選擇。 –

4
SELECT DVDTitle AS "DVD Title" 
FROM DVD d 
left outer join Rental r on d.DVDId = r.DVDId 
WHERE r.MemberId = 'AL240' 
    and r.DVDId is null 

確保您有索引:

d.DVDId 
r.DVDId 
r.MemberId 
+0

非常感謝你RedFilter –

+0

@ K-Seeker出於好奇,你是否觀察到實際的性能提升? –

+0

嗨亞倫,有一個重大的改善。我還沒有測試過你的消化不良,但我嘗試了NOT EXISTS,並沒有比NO IN子查詢差多少。我會及時向大家發佈。再次感謝。擔 –