Apakah ada praktik terbaik antara menggunakan LEFT JOIN atau format NOT EXISTS?
Apa manfaat menggunakan yang satu dari yang lain?
Jika tidak ada, yang mana yang lebih disukai?
SELECT *
FROM tableA A
LEFT JOIN tableB B
ON A.idx = B.idx
WHERE B.idx IS NULL
SELECT *
FROM tableA A
WHERE NOT EXISTS
(SELECT idx FROM tableB B WHERE B.idx = A.idx)
Saya menggunakan kueri dalam Access terhadap database SQL Server.
sql-server
join
exists
Michael Richardson
sumber
sumber
WHERE A.idx NOT IN (...)
adalah tidak identik karena perilaku trivalen dariNULL
(yaituNULL
tidak sama denganNULL
(atau tidak sama), oleh karena itu jika Anda memiliki salahNULL
ditableB
Anda akan mendapatkan hasil yang tak terduga!)Jawaban:
Perbedaan terbesar adalah tidak di gabung vs tidak ada, itu (seperti yang tertulis), itu
SELECT *
.Pada contoh pertama, Anda mendapatkan semua kolom dari keduanya
A
danB
, sedangkan dalam contoh kedua, Anda hanya mendapatkan kolom dariA
.Dalam SQL Server, varian kedua sedikit lebih cepat dalam contoh yang dibuat sangat sederhana:
Buat dua tabel sampel:
Masukkan 10.000 baris ke setiap tabel:
Hapus setiap baris ke-5 dari tabel kedua:
Lakukan dua
SELECT
varian pernyataan tes :Rencana eksekusi:
Varian kedua tidak perlu melakukan operasi filter karena dapat menggunakan operator anti-semi join kiri.
sumber
Secara logis mereka identik, tetapi
NOT EXISTS
lebih dekat dengan AntiSemiJoin yang Anda minta, dan umumnya lebih disukai. Ini juga menyoroti lebih baik bahwa Anda tidak dapat mengakses kolom di B, karena itu hanya digunakan sebagai filter (sebagai lawan tersedia dengan nilai NULL).Bertahun-tahun yang lalu (SQL Server 6.0 ish),
LEFT JOIN
lebih cepat, tetapi itu tidak terjadi untuk waktu yang lama. Hari-hari ini,NOT EXISTS
sedikit lebih cepat.Dampak terbesar dalam Access adalah bahwa
JOIN
metode ini harus menyelesaikan gabungan sebelum memfilternya, membangun kumpulan yang bergabung dalam memori. MenggunakannyaNOT EXISTS
memeriksa baris tetapi tidak mengalokasikan ruang untuk kolom. Plus, ia berhenti mencari begitu menemukan baris. Kinerja bervariasi sedikit lebih banyak di Access, tetapi aturan umum yangNOT EXISTS
cenderung sedikit lebih cepat. Saya akan cenderung mengatakan itu "praktik terbaik", karena ada lebih banyak faktor yang terlibat.sumber
Pengecualian yang saya perhatikan sebagai
NOT EXISTS
yang lebih unggul (namun sedikit)LEFT JOIN ... WHERE IS NULL
adalah ketika menggunakan Server Tertaut .Dari memeriksa rencana eksekusi, tampak bahwa
NOT EXISTS
operator dieksekusi dalam mode loop bersarang. Dimana dijalankan pada basis per baris (yang saya kira masuk akal).Contoh rencana eksekusi yang menunjukkan perilaku ini:
sumber
INSERT INTO #t (a,b,c) SELECT a,b,c FROM LinkedServer.database.dbo.table WHERE x=y
kemudian menjalankanNOT EXISTS (...)
klausa terhadap salinan sementara dari database.Secara umum, mesin akan membuat rencana eksekusi berdasarkan dasarnya pada:
Untuk (4):
Rencana "tidak ada" mendorong rencana pencarian berdasarkan pada tabel B. Ini adalah pilihan yang baik ketika tabel A kecil dan tabel B besar (dan indeks ada di B).
Rencana "antijoin" adalah pilihan yang baik ketika tabel A sangat besar atau tabel B sangat kecil atau tidak ada indeks pada B dan mengembalikan set hasil yang besar.
Namun itu hanya "dorongan", seperti input tertimbang. A (1), (2), (3) yang kuat sering membuat pilihan untuk (4) diperdebatkan.
(Mengabaikan efek dari contoh Anda mengembalikan kolom yang berbeda karena *, dialamatkan oleh jawaban @MaxVernon.).
sumber