我有一個動態查詢,可以識別成員還沒有租用的CD。我使用NOT IN子查詢,但是當我有大的成員表時,它會讓它們真的很慢。任何建議如何優化查詢NOT IN子查詢優化
SELECT DVDTitle AS "DVD Title"
FROM DVD
WHERE DVDId NOT IN
(SELECT DISTINCT DVDId FROM Rental WHERE MemberId = AL240);
感謝
我有一個動態查詢,可以識別成員還沒有租用的CD。我使用NOT IN子查詢,但是當我有大的成員表時,它會讓它們真的很慢。任何建議如何優化查詢NOT IN子查詢優化
SELECT DVDTitle AS "DVD Title"
FROM DVD
WHERE DVDId NOT IN
(SELECT DISTINCT DVDId FROM Rental WHERE MemberId = AL240);
感謝
使用NOT EXISTS
將有表現略好,因爲它可以「短路」,而不是評估每場比賽的整個集合。至少,它不會比NOT IN
或OUTER 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?
如果兩個'DVDId'列都不能爲空,我會期望'NOT IN'和'NOT EXISTS'具有相同的計劃。如果兩者都可以爲空,那麼'NOT IN'版本[需要做更多的工作](http://stackoverflow.com/a/11074428/73226) –
@MartinSmith是的,這是真的,但請注意,我也消除了'DISTINCT ' –
如果您不確定,只是默認爲不存在。它幾乎總是反連接的最佳選擇。 –
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
非常感謝你RedFilter –
@ K-Seeker出於好奇,你是否觀察到實際的性能提升? –
嗨亞倫,有一個重大的改善。我還沒有測試過你的消化不良,但我嘗試了NOT EXISTS,並沒有比NO IN子查詢差多少。我會及時向大家發佈。再次感謝。擔 –
哪些表定義,包括列的爲空和索引? –
你有'Rental(MemberID,DVDId)'的索引嗎? –
給了我們更多的信息,比如行數,索引等 –