Kinerja SQL JOIN vs IN?

164

Saya memiliki kasus di mana menggunakan GABUNGAN atau IN akan memberi saya hasil yang benar ... Yang biasanya memiliki kinerja lebih baik dan mengapa? Berapa tergantung pada server database apa yang Anda jalankan? (FYI saya menggunakan MSSQL)

Polaris878
sumber
:) Saya benar-benar mencari artikel yang berbeda yang saya gunakan ketika saya meneliti sesuatu yang serupa beberapa waktu lalu, dan menemukan itu secara tidak sengaja
AdaTheDev
Maaf untuk kemungkinan penipuan ... tidak menemukan pertanyaan itu ketika saya mencari
Polaris878

Jawaban:

196

Secara umum, INdan JOINberbagai pertanyaan yang dapat menghasilkan hasil yang berbeda.

SELECT  a.*
FROM    a
JOIN    b
ON      a.col = b.col

tidak sama dengan

SELECT  a.*
FROM    a
WHERE   col IN
        (
        SELECT  col
        FROM    b
        )

, kecuali b.colunik.

Namun, ini adalah sinonim untuk kueri pertama:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT col
        FROM    b
        )
ON      b.col = a.col

Jika kolom bergabung adalah UNIQUEdan ditandai seperti itu, kedua permintaan ini menghasilkan paket yang sama di SQL Server.

Jika tidak, maka INlebih cepat dari JOINpada DISTINCT.

Lihat artikel ini di blog saya untuk detail kinerja:

Quassnoi
sumber
Ya masuk akal bahwa mereka akan melakukan hal yang sama jika kolom yang bergabung adalah unik (yang ada dalam kasus saya)
Polaris878
1
Pada catatan yang sama, haruskah saya menggunakan IN (SELECT DISTINCT ...) atau cukup IN (SELECT ...)?
moo
8
@ orlandu63: INmenyiratkan DISTINCT. SQL Servercukup cerdas untuk menyadarinya, dan akan menghasilkan rencana yang sama untuk kedua pertanyaan. Namun, tidak yakin bagaimana RDBMSperilaku orang lain.
Quassnoi
>> IN dan JOIN adalah pertanyaan berbeda yang dapat menghasilkan hasil yang berbeda. Bisakah Anda jelaskan mengapa itu menghasilkan hasil yang berbeda dalam kasus ini bahkan jika b.col tidak unik?
Abhijeet
menjelaskanextended.com/2009/06/16/in-vs-join-vs-exists Sangat membantu saya .. Terima kasih ..
Abbas Galiyakotwala
6

Itu agak sulit dikatakan - untuk benar-benar mengetahui mana yang bekerja lebih baik, Anda harus benar-benar membuat profil waktu eksekusi.

Sebagai aturan umum, saya pikir jika Anda memiliki indeks pada kolom kunci asing Anda, dan jika Anda hanya menggunakan kondisi INNER JOIN, maka JOIN akan sedikit lebih cepat.

Tetapi begitu Anda mulai menggunakan OUTER JOIN, atau jika Anda tidak memiliki indeks kunci asing, IN mungkin lebih cepat.

Marc

marc_s
sumber
Saya juga memikirkan hal ini ... karena tampaknya BERGABUNG adalah kasus yang lebih umum dan lebih mungkin dioptimalkan
Polaris878
4

Langgan menarik pada perbedaan logis: SQL Server: BERGABUNG vs DALAM vs ADA - perbedaan logis

Saya cukup yakin bahwa dengan asumsi bahwa hubungan dan indeks dipertahankan, Gabung akan berkinerja lebih baik secara keseluruhan (lebih banyak upaya untuk bekerja dengan operasi itu daripada yang lain). Jika Anda memikirkannya secara konseptual maka perbedaannya antara 2 kueri dan 1 kueri.

Anda perlu menghubungkannya ke Query Analyzer dan mencobanya dan lihat perbedaannya. Lihat juga Rencana Eksekusi Kueri dan cobalah untuk meminimalkan langkah-langkah.

AdamSane
sumber
4

Utas ini cukup lama tetapi masih sering disebutkan. Untuk selera pribadi saya itu agak tidak lengkap, karena ada cara lain untuk meminta database dengan kata kunci yang ada yang saya temukan lebih cepat lebih sering daripada tidak.

Jadi, jika Anda hanya tertarik pada nilai dari tabel, Anda dapat menggunakan kueri ini:

SELECT  a.*
FROM    a
WHERE   EXISTS (
    SELECT  *
    FROM    b
    WHERE   b.col = a.col
    )

Perbedaannya mungkin besar jika col tidak diindeks, karena db tidak harus menemukan semua catatan dalam b yang memiliki nilai yang sama dalam col, hanya harus menemukan yang pertama. Jika tidak ada indeks pada b.col dan banyak catatan dalam pemindaian tabel ba mungkin konsekuensinya. Dengan IN atau GABUNG, ini akan menjadi pemindaian tabel penuh, dengan EXISTS ini hanya pemindaian tabel parsial (sampai catatan pencocokan pertama ditemukan).

Jika ada banyak catatan dalam b yang memiliki nilai col yang sama Anda juga akan membuang banyak memori untuk membaca semua catatan ini dalam ruang sementara hanya untuk menemukan bahwa kondisi Anda terpenuhi. Dengan adanya ini biasanya dapat dihindari.

Saya sering menemukan EXIS lebih cepat daripada DI walaupun ada indeks. Itu tergantung pada sistem basis data (pengoptimal), data dan terakhir pada jenis indeks yang digunakan.

S.Roeper
sumber
3
Pada MSSql fakta yang ada lebih baik daripada IN tampaknya tidak benar. Untuk informasi lebih lanjut: jelaskanextext.com/2009/06/16/in-vs-join-vs-exists Di sini Anda dapat membaca bahwa: "Banyak yang berpendapat bahwa EXISTS lebih efisien daripada IN, karena EXISTS hanya mengembalikan satu baris. Ini adalah tidak benar untuk SQL Server. Seperti yang dapat kita lihat dari contoh di atas, EXIS dan IN menghasilkan rencana yang persis sama. Ini karena EXIS lebih fleksibel daripada IN. IN selalu dapat ditulis ulang sebagai EXIS (menggunakan kondisi WHERE sederhana dengan equijoin ) tetapi tidak sebaliknya. "
Micaël Félix
3

Setiap implementasi database tetapi Anda mungkin dapat menebak bahwa mereka semua memecahkan masalah umum dengan cara yang kurang lebih sama. Jika Anda menggunakan MSSQL, lihatlah rencana eksekusi yang dihasilkan. Anda dapat melakukan ini dengan menyalakan profiler dan rencana eksekusi. Ini akan memberi Anda versi teks saat Anda menjalankan perintah.

Saya tidak yakin apa versi MSSQL yang Anda gunakan tetapi Anda bisa mendapatkan yang grafis di SQL Server 2000 di penganalisis kueri. Saya yakin bahwa fungsi ini mengintai di SQL Server Studio Manager di versi yang lebih baru.

Lihatlah rencana pengeluarannya. Sedapat mungkin hindari pemindaian tabel kecuali tentu saja meja Anda kecil dalam hal pemindaian tabel lebih cepat daripada menggunakan indeks. Baca tentang berbagai operasi gabungan yang dihasilkan setiap skenario.

uriDium
sumber
1

Pengoptimal harus cukup pintar untuk memberikan Anda hasil yang sama baik untuk kueri normal. Periksa rencana eksekusi dan mereka harus memberi Anda hal yang sama. Jika tidak, saya biasanya akan menganggap GABUNG lebih cepat. Semua sistem berbeda, jadi Anda harus memastikan kode pada sistem Anda.

Joel Coehoorn
sumber
5
Harus lakukan? Mungkin. Melakukannya? Lihat posting saya.
cletus