Dugaan pertama saya adalah ATAU berkinerja lebih baik, kecuali mesin SQL mengubah IN menjadi ATAU di belakang layar. Pernahkah Anda melihat rencana kueri dari keduanya?
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 INmengurutkan daftar dan kemudian menggunakan pencarian biner. Saya akan membayangkan bahwa ORmengevaluasi mereka satu per satu tanpa urutan tertentu. Jadi INlebih 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);1row fetched in0.0032(1.2679 seconds)SELECT COUNT(*)FROM t_inner WHERE val =1000OR val =2000OR val =3000OR val =4000OR val =5000OR val =6000OR val =7000OR val =8000OR val =9000;1row fetched in0.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.
Jika optimizer bernilai garam, mereka harus melakukan hal yang sama.
Janick Bernet
27
@inflagranti: Sayangnya tidak ada optimizer yang sempurna. Pengoptimal adalah program yang sangat kompleks dan setiap implementasi akan memiliki kekuatan dan kelemahannya sendiri. Inilah sebabnya saya katakan Anda harus membuat profil pada implementasi tertentu. Saya membayangkan bahwa struktur ekstra dari INmetode ini membuatnya lebih mudah untuk dioptimalkan daripada sejumlah ORklausa yang mungkin terkait . Saya akan terkejut jika ada mesin di mana ORmetode ini lebih cepat, tetapi saya tidak terkejut bahwa ada kalanya OR lebih lambat.
Mark Byers
2
@MarkByers Tidak bisakah pengoptimal selalu mengganti beberapa ORdengan IN?
tymtam
36
Cara terbaik untuk mengetahuinya adalah dengan melihat Rencana Eksekusi.
Saya mencobanya dengan Oracle , dan itu persis sama.
CREATETABLE 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')
Apa yang terjadi di Oracle jika Anda memiliki lebih dari 3 nilai yang Anda uji? Apakah Anda tahu jika Oracle tidak dapat melakukan optimasi pencarian biner yang sama dengan MySQL atau apakah itu melakukan keduanya?
Mark Byers
2
@ Markus Byers: Saya mencoba permintaan yang sama dengan 10 nilai, masih hasilnya sama. Perhatikan, bahwa pengoptimal menggunakan nilai saya dalam urutan abjad. Saya tidak akan terkejut jika Oracle melakukan beberapa optimasi internal dari filter itu ...
Peter Lang
5
Oracle juga memiliki INLIST ITERATORoperasi, yang akan dipilih jika ada indeks yang bisa digunakan. Namun, ketika saya mencobanya, keduanya INdan ORberakhir dengan rencana eksekusi yang sama.
Cheran Shunmugavel
7
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.
Saya pikir oracle cukup pintar untuk mengubah yang kurang efisien (mana pun itu) menjadi yang lain. Jadi saya pikir jawabannya lebih tergantung pada keterbacaan masing-masing (di mana saya pikir itu INjelas menang)
ORmasuk akal (dari sudut pandang keterbacaan), ketika ada nilai yang lebih sedikit untuk dibandingkan.
INsangat berguna esp. ketika Anda memiliki sumber dinamis, yang Anda inginkan nilainya dibandingkan.
Alternatif lain adalah menggunakan JOINtabel sementara.
Saya tidak berpikir kinerja harus menjadi masalah, asalkan Anda memiliki indeks yang diperlukan.
Jawaban:
Saya berasumsi Anda ingin mengetahui perbedaan kinerja antara yang berikut:
Menurut manual untuk MySQL jika nilainya konstan
IN
mengurutkan daftar dan kemudian menggunakan pencarian biner. Saya akan membayangkan bahwaOR
mengevaluasi mereka satu per satu tanpa urutan tertentu. JadiIN
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:
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.
sumber
IN
metode ini membuatnya lebih mudah untuk dioptimalkan daripada sejumlahOR
klausa yang mungkin terkait . Saya akan terkejut jika ada mesin di manaOR
metode ini lebih cepat, tetapi saya tidak terkejut bahwa ada kalanya OR lebih lambat.OR
denganIN
?Cara terbaik untuk mengetahuinya adalah dengan melihat Rencana Eksekusi.
Saya mencobanya dengan Oracle , dan itu persis sama.
Meskipun kueri menggunakan
IN
, Rencana Eksekusi mengatakan bahwa ia menggunakanOR
:sumber
INLIST ITERATOR
operasi, yang akan dipilih jika ada indeks yang bisa digunakan. Namun, ketika saya mencobanya, keduanyaIN
danOR
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.
sumber
Saya pikir oracle cukup pintar untuk mengubah yang kurang efisien (mana pun itu) menjadi yang lain. Jadi saya pikir jawabannya lebih tergantung pada keterbacaan masing-masing (di mana saya pikir itu
IN
jelas menang)sumber
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.
sumber
Saya melakukan query SQL dalam sejumlah besar OR (350). Postgres melakukannya 437.80ms .
Sekarang gunakan IN:
23,18 ms
sumber