Ketika berhadapan dengan database besar, yang berkinerja lebih baik, IN
atau OR
dalam SQL Where
-clause?
Apakah ada perbedaan tentang cara mereka dieksekusi?
Ketika berhadapan dengan database besar, yang berkinerja lebih baik, IN
atau OR
dalam SQL Where
-clause?
Apakah ada perbedaan tentang cara mereka dieksekusi?
Jawaban:
Saya berasumsi Anda ingin mengetahui perbedaan kinerja antara yang berikut:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
Menurut manual untuk MySQL jika nilainya konstan IN
mengurutkan daftar dan kemudian menggunakan pencarian biner. Saya akan membayangkan bahwa OR
mengevaluasi mereka satu per satu tanpa urutan tertentu. Jadi IN
lebih cepat dalam beberapa keadaan.
Cara terbaik untuk mengetahuinya adalah dengan membuat profil pada database Anda dengan data spesifik Anda untuk melihat mana yang lebih cepat.
Saya mencoba keduanya pada MySQL dengan 10.00000 baris. Ketika kolom diindeks tidak ada perbedaan kinerja yang jelas - keduanya hampir instan. Ketika kolom tidak diindeks saya mendapat hasil ini:
SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)
SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)
Jadi dalam hal ini metode menggunakan OR sekitar 30% lebih lambat. Menambahkan lebih banyak istilah membuat perbedaan lebih besar. Hasil dapat bervariasi pada basis data lain dan pada data lain.
IN
metode ini membuatnya lebih mudah untuk dioptimalkan daripada sejumlah OR
klausa yang mungkin terkait . Saya akan terkejut jika ada mesin di mana OR
metode ini lebih cepat, tetapi saya tidak terkejut bahwa ada kalanya OR lebih lambat.
OR
dengan IN
?
Cara terbaik untuk mengetahuinya adalah dengan melihat Rencana Eksekusi.
Saya mencobanya dengan Oracle , dan itu persis sama.
CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );
SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );
Meskipun kueri menggunakan IN
, Rencana Eksekusi mengatakan bahwa ia menggunakan OR
:
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 1416 | 163 (2)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| PERFORMANCE_TEST | 8 | 1416 | 163 (2)| 00:00:02 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR
"OBJECT_NAME"='DBMS_STANDARD')
INLIST ITERATOR
operasi, yang akan dipilih jika ada indeks yang bisa digunakan. Namun, ketika saya mencobanya, keduanya IN
dan OR
berakhir dengan rencana eksekusi yang sama.
Operator OR membutuhkan proses evaluasi yang jauh lebih kompleks daripada konstruksi IN karena memungkinkan banyak kondisi, tidak hanya sama seperti IN.
Berikut ini adalah apa yang dapat Anda gunakan dengan ATAU tetapi yang tidak kompatibel dengan IN: lebih besar. lebih besar atau sama, lebih sedikit, lebih sedikit atau sama dengan, LIKE dan beberapa lagi seperti oracle REGEXP_LIKE. Selain itu pertimbangkan bahwa kondisinya mungkin tidak selalu membandingkan nilai yang sama.
Untuk pengoptimal kueri, lebih mudah untuk mengelola operator IN karena hanya konstruk yang mendefinisikan operator OR pada beberapa kondisi dengan = operator pada nilai yang sama. Jika Anda menggunakan operator OR, pengoptimal mungkin tidak menganggap bahwa Anda selalu menggunakan operator = pada nilai yang sama dan, jika tidak melakukan elaborasi yang lebih dalam dan jauh lebih kompleks, mungkin bisa mengecualikan bahwa mungkin hanya ada = operator untuk nilai yang sama pada semua kondisi yang terlibat, dengan konsekuensinya menghalangi metode pencarian yang dioptimalkan seperti pencarian biner yang telah disebutkan.
[EDIT] Mungkin pengoptimal mungkin tidak menerapkan proses evaluasi IN yang dioptimalkan, tetapi ini tidak mengecualikan bahwa sekali saja hal itu bisa terjadi (dengan pemutakhiran versi basis data). Jadi, jika Anda menggunakan operator ATAU yang diuraikan elaborasi tidak akan digunakan dalam kasus Anda.
OR
masuk akal (dari sudut pandang keterbacaan), ketika ada nilai yang lebih sedikit untuk dibandingkan.
IN
sangat berguna esp. ketika Anda memiliki sumber dinamis, yang Anda inginkan nilainya dibandingkan.
Alternatif lain adalah menggunakan JOIN
tabel sementara.
Saya tidak berpikir kinerja harus menjadi masalah, asalkan Anda memiliki indeks yang diperlukan.
Saya melakukan query SQL dalam sejumlah besar OR (350). Postgres melakukannya 437.80ms .
Sekarang gunakan IN:
23,18 ms