IN kaçınılmalıdır?


14

Bazı SQL Server geliştiricileri arasında NOT IN, çok yavaş olan yaygın bir inanç ve sorgular aynı sonucu döndürecek ancak "kötü" anahtar kelimeleri kullanmayacak şekilde yeniden yazılmalıdır. ( örnek ).

Bunun bir gerçeği var mı?

Örneğin, SQL Server'da (hangi sürüm?) Kullanılan sorguların NOT IN, kullanan eşdeğer bir sorgudan daha kötü bir yürütme planına sahip olmasına neden olan bilinen bir hata var mı?

  • bir LEFT JOINile birleştirilmiş NULLçek veya
  • (SELECT COUNT(*) ...) = 0içinde WHEREmaddesi?

7
Yine de bu makale oldukça yanlış. "In" gerekmez "TableOne her satır için aynı sorguyu tekrar tekrar çalıştırmak zorunda". Poster inanmak görünüyor IN/ NOT INher zaman iç içe döngüler ile uygulanacaktır. Ve ne stops SQL Server from creating a ‘plan’demek istediğimi bilmiyorum .
Martin Smith

5
@Heinzi Bağlantı verdiğiniz makale ateşte ölmeli, saçmalıklarla dolu. Gibi: "IN değiştirmek için, bir iç birleşim kullanın Onlar etkili aynı şeydir.". Sorun şu ki, aynı şey değiller. SQL-Server davranışı hakkında bir şey analiz etmek için temel SQL, yani birleştirme ve yarı birleştirme arasındaki fark bilmeyen birine güvenmezdim.
ypercubeᵀᴹ

Yanıtlar:


14

Çok yavaş olmakla ilgisi olduğunu düşünmüyorum; potansiyel olarak yanlış olmakla ilgilidir. Örneğin, aşağıdaki veriler - bireysel bir müşteri veya bir B2B iş ortağı tarafından verilebilecek siparişler verildiğinde:

DECLARE @Customers TABLE(CustomerID INT);

INSERT @Customers VALUES(1),(2);

DECLARE @Orders TABLE(OrderID INT, CustomerID INT, CompanyID INT);

INSERT @Orders VALUES(10,1,NULL),(11,NULL,5);

Diyelim ki hiç sipariş vermeyen tüm müşterileri bulmak istiyorum. Veriler göz önüne alındığında, sadece bir tane var: müşteri # 2. İşte bu bilgileri bulmak için bir sorgu yazma hakkında üç yolu: (diğerleri vardır):

SELECT [NOT IN] = CustomerID FROM @Customers 
  WHERE CustomerID NOT IN (SELECT CustomerID FROM @Orders);

SELECT [NOT EXISTS] = CustomerID FROM @Customers AS c 
  WHERE NOT EXISTS (SELECT 1 FROM @Orders AS o
  WHERE o.CustomerID = c.CustomerID);

SELECT [EXCEPT] = CustomerID FROM @Customers
EXCEPT SELECT CustomerID FROM @Orders;

Sonuçlar:

NOT IN
------
                 -- <-- no results. Is that what you expected?

NOT EXISTS
----------
2

EXCEPT
------
2

Şimdi, bazı performans sorunları da var ve bu blog yazısında onlar hakkında konuşuyorum . Verilere ve endekslere bağlı olarak, NOT EXISTSgenellikle daha iyi performans gösterir NOT INve daha kötü performans gösterip gösteremeyeceğini bilmiyorum. Ayrıca EXCEPT, farklı bir sıralama işlemi getirebileceğini de unutmamalısınız , böylece farklı veriler elde edebilirsiniz (yine kaynağa bağlı olarak). Ve popüler LEFT OUTER JOIN ... WHERE right.column IS NULLdesen her zaman en kötü performanstır.

Martin Smith, SO'ya verdiği yanıtta da çok iyi destekleyici bilgiye sahiptir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.