Haruskah DI DALAM dihindari?


14

Di antara beberapa pengembang SQL Server, ini adalah kepercayaan luas yang NOT INsangat lambat , dan pertanyaan harus ditulis ulang sehingga mereka memberikan hasil yang sama tetapi tidak menggunakan kata kunci "jahat". ( contoh ).

Apakah ada kebenarannya?

Apakah ada, misalnya, beberapa bug yang dikenal di SQL Server (versi mana?) Yang menyebabkan kueri menggunakan NOT INmemiliki rencana eksekusi yang lebih buruk daripada kueri setara yang menggunakan

  • a LEFT JOINdikombinasikan dengan NULLcek atau
  • (SELECT COUNT(*) ...) = 0dalam WHEREklausa?

7
Artikel itu sangat tidak akurat. "Dalam" tidak "harus menjalankan kueri yang sama berulang-ulang untuk setiap baris di TableOne". Poster di sana tampaknya percaya bahwa IN/ NOT INakan selalu diimplementasikan dengan loop bersarang. Dan saya tidak tahu apa stops SQL Server from creating a ‘plan’yang dimaksudkan.
Martin Smith

5
@Heinzi Artikel yang Anda tautkan, harus mati terbakar, penuh omong kosong. Seperti: "Untuk mengganti IN, kami menggunakan INNER JOIN. Mereka secara efektif adalah hal yang sama." Masalahnya, mereka bukan hal yang sama. Saya tidak akan mempercayai seseorang yang tidak tahu SQL dasar, yaitu perbedaan antara bergabung dan semi bergabung, untuk menganalisis apa pun tentang perilaku SQL-Server.
ypercubeᵀᴹ

Jawaban:


14

Saya tidak berpikir itu ada hubungannya dengan menjadi sangat lambat; itu ada hubungannya dengan menjadi berpotensi tidak akurat. Misalnya, diberi data berikut - pesanan yang dapat ditempatkan baik oleh pelanggan individu, atau mitra B2B:

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);

Katakanlah saya ingin menemukan semua pelanggan yang belum pernah melakukan pemesanan. Mengingat data, hanya ada satu: pelanggan # 2. Berikut adalah tiga cara yang dapat saya lakukan untuk menulis kueri untuk menemukan informasi itu (ada yang lain):

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;

Hasil:

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

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

EXCEPT
------
2

Sekarang, ada beberapa masalah kinerja juga, dan saya membicarakannya di posting blog ini . Tergantung pada data dan indeks, NOT EXISTSbiasanya akan mengungguli NOT IN, dan saya tidak tahu apakah itu bisa berkinerja lebih buruk. Anda juga harus mencatat bahwa EXCEPTdapat memperkenalkan operasi penyortiran yang berbeda, sehingga Anda dapat berakhir dengan data yang berbeda (sekali lagi, tergantung pada sumbernya). Dan bahwa LEFT OUTER JOIN ... WHERE right.column IS NULLpola populer selalu merupakan yang terburuk.

Martin Smith juga memiliki banyak informasi pendukung yang bagus dalam jawabannya di SO .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.