Saya bertanya-tanya apakah ada perbedaan dalam hal kinerja antara berikut ini
SELECT ... FROM ... WHERE someFIELD IN(1,2,3,4)
SELECT ... FROM ... WHERE someFIELD between 0 AND 5
SELECT ... FROM ... WHERE someFIELD = 1 OR someFIELD = 2 OR someFIELD = 3 ...
atau akankah MySQL mengoptimalkan SQL dengan cara yang sama dengan kompiler akan mengoptimalkan kode?
EDIT: Mengubah AND
to OR
's untuk alasan yang disebutkan dalam komentar.
mysql
sql
performance
optimization
Scott
sumber
sumber
s I could say that it can also be converted to UNION
yang direkomendasikan untuk mengganti OR untuk mengoptimalkan kueri.Jawaban:
Saya perlu tahu ini dengan pasti, jadi saya membandingkan kedua metode ini. Secara konsisten saya menemukan
IN
jauh lebih cepat daripada menggunakanOR
.Jangan percaya orang yang memberikan "pendapat" mereka, sains adalah soal pengujian dan bukti.
Saya menjalankan loop 1000x kueri yang setara (untuk konsistensi, saya menggunakan
sql_no_cache
):IN
: 2.34969592094sOR
: 5.83781504631sPembaruan:
(Saya tidak memiliki kode sumber untuk tes asli, seperti 6 tahun yang lalu, meskipun ia mengembalikan hasil dalam kisaran yang sama dengan tes ini)
Dalam permintaan beberapa kode sampel untuk menguji ini, berikut ini adalah use case yang paling sederhana. Menggunakan Eloquent untuk kesederhanaan sintaksis, setara SQL mentah mengeksekusi yang sama.
sumber
IN
pernyataan itu sekitar 30% lebih cepat daripadaOR
.Do not believe people who give their "opinion"
Anda 100% benar, sayangnya Stack Overflow penuh dengan merekaReturns 1 if expr is equal to any of the values in the IN list, else returns 0. If all values are constants, they are evaluated according to the type of expr and sorted. The search for the item then is done using a binary search. This means
IN is very quick if the IN value list consists entirely of constants
. Otherwise, type conversion takes place according to the rules described at Type Conversion, but applied to all the arguments.
IN
Saya juga melakukan tes untuk Googler masa depan. Jumlah total hasil yang dikembalikan adalah 7264 dari 10.000
Permintaan ini membutuhkan beberapa
0.1239
detikPermintaan ini membutuhkan beberapa
0.0433
detikIN
3 kali lebih cepat dariOR
sumber
OR
: terbaik untuk menggunakan ekspresi sekecil mungkin.Jawaban yang diterima tidak menjelaskan alasannya.
Di bawah ini dikutip dari High Performance MySQL, 3rd Edition.
sumber
Saya pikir BETWEEN akan lebih cepat karena harus diubah menjadi:
Ini adalah pemahaman saya bahwa IN akan dikonversi ke sekelompok pernyataan ATAU. Nilai IN adalah kemudahan penggunaan. (Menghemat karena harus mengetik setiap nama kolom beberapa kali dan juga membuatnya lebih mudah untuk digunakan dengan logika yang ada - Anda tidak perlu khawatir tentang AND / ATAU didahulukan karena IN adalah satu pernyataan. Dengan banyak pernyataan ATAU, Anda memiliki untuk memastikan Anda mengelilinginya dengan tanda kurung untuk memastikan mereka dievaluasi sebagai satu syarat.)
Satu-satunya jawaban nyata untuk pertanyaan Anda adalah PROFIL QUERIES ANDA . Maka Anda akan tahu apa yang paling berhasil dalam situasi khusus Anda.
sumber
Itu tergantung pada apa yang Anda lakukan; seberapa luas jangkauannya, apa tipe datanya (Saya tahu contoh Anda menggunakan tipe data numerik tetapi pertanyaan Anda juga dapat diterapkan pada banyak tipe data yang berbeda).
Ini adalah contoh di mana Anda ingin menulis kueri dua arah; membuatnya bekerja dan kemudian gunakan MENJELASKAN untuk mengetahui perbedaan eksekusi.
Saya yakin ada jawaban konkret untuk ini tetapi ini adalah bagaimana saya akan, secara praktis, mencari tahu jawaban untuk pertanyaan saya.
Ini mungkin bisa membantu: http://forge.mysql.com/wiki/Top10SQLPerformanceTips
Salam,
Frank
sumber
Saya pikir salah satu penjelasan untuk pengamatan sunseeker adalah MySQL sebenarnya mengurutkan nilai-nilai dalam pernyataan IN jika mereka semua nilai statis dan menggunakan pencarian biner, yang lebih efisien daripada alternatif polos ATAU. Saya tidak ingat di mana saya membacanya, tetapi hasil sunseeker tampaknya menjadi bukti.
sumber
Tepat ketika Anda berpikir itu aman ...
Apa nilai Anda
eq_range_index_dive_limit
? Secara khusus, apakah Anda memiliki lebih banyak atau lebih sedikit item dalamIN
klausa?Ini tidak akan termasuk Tolok Ukur, tetapi akan sedikit mengintip ke dalam kerja batin. Mari kita gunakan alat untuk melihat apa yang sedang terjadi - Jejak Pengoptimal.
Kueri:
SELECT * FROM canada WHERE id ...
Dengan
OR
nilai 3 , bagian dari jejaknya terlihat seperti:...
...
Perhatikan bagaimana ICP diberikan
ORs
. Ini menyiratkan bahwaOR
tidak berubah menjadiIN
, dan InnoDB akan melakukan banyak=
tes melalui ICP. (Saya tidak merasa perlu mempertimbangkan MyISAM.)(Ini adalah 5.6.22-71.0-log Percona;
id
ini adalah indeks sekunder.)Sekarang untuk IN () dengan beberapa nilai
eq_range_index_dive_limit
= 10; ada 8 nilai....
...
Perhatikan bahwa
IN
tampaknya tidak berubah menjadiOR
.Catatan samping: Perhatikan bahwa nilai konstan diurutkan . Ini bisa bermanfaat dalam dua cara:
Akhirnya, IN () dengan banyak nilai
...
...
Catatan: Saya membutuhkan ini karena besarnya jejak:
sumber
ATAU akan paling lambat. Apakah IN atau ANTARA lebih cepat akan tergantung pada data Anda, tapi saya berharap ANTARA lebih cepat secara normal karena dapat dengan mudah mengambil rentang dari indeks (dengan asumsi someField diindeks).
sumber
Di bawah ini adalah detail dari 6 pertanyaan menggunakan MySQL 5.6 @SQLFiddle
Singkatnya, 6 kueri mencakup kolom yang diindeks secara independen dan 2 kueri digunakan per tipe data. Semua kueri menghasilkan penggunaan indeks terlepas dari IN () atau OR yang digunakan.
Saya benar-benar hanya ingin menyanggah pernyataan yang dibuat ATAU berarti tidak ada indeks yang dapat digunakan. Ini tidak benar. Indeks dapat digunakan dalam kueri menggunakan OR sebagai 6 kueri dalam tampilan contoh berikut.
Juga nampak bagi saya bahwa banyak orang telah mengabaikan fakta bahwa IN () adalah jalan pintas sintaks untuk satu set OR. Pada skala kecil perbedaan kinerja antara menggunakan IN () -v- OR sangat marginal.
Meskipun pada skala yang lebih besar IN () tentu lebih nyaman, tetapi masih sama dengan serangkaian kondisi ATAU secara logis. Perubahan keadaan untuk setiap kueri sehingga menguji kueri Anda di tabel Anda selalu yang terbaik.
Ringkasan dari 6 menjelaskan rencana, semua "Menggunakan kondisi indeks" (gulir ke kanan)
SQL Fiddle
Pengaturan Skema MySQL 5.6 :
.
Pertanyaan 1 :
Hasil :
Pertanyaan 2 :
Hasil :
Pertanyaan 3 :
Hasil :
Pertanyaan 4 :
Hasil :
Pertanyaan 5 :
Hasil :
Pertanyaan 6 :
Hasil :
sumber
Saya yakin mereka sama, Anda dapat menjalankan tes dengan melakukan hal berikut:
loop di atas "dalam (1,2,3,4)" 500 kali dan lihat berapa lama. loop di atas versi "= 1 atau = 2 atau = 3 ..." 500 kali dan lihat berapa lama itu berjalan.
Anda juga bisa mencoba cara bergabung, jika someField adalah indeks dan meja Anda besar itu bisa lebih cepat ...
Saya mencoba metode bergabung di atas pada SQL Server saya dan hampir sama dengan di (1,2,3,4), dan keduanya menghasilkan pencarian indeks berkerumun. Saya tidak yakin bagaimana MySQL akan menanganinya.
sumber
2018 : IN (...) lebih cepat. Tetapi > = && <= bahkan lebih cepat daripada IN .
Inilah tolok ukur saya .
sumber
Dari apa yang saya mengerti tentang cara kompiler mengoptimalkan jenis pertanyaan ini, menggunakan klausa IN lebih efisien daripada beberapa klausa ATAU. Jika Anda memiliki nilai di mana klausa BETWEEN dapat digunakan, itu masih lebih efisien.
sumber
Saya tahu bahwa, selama Anda memiliki indeks di Field, BETWEEN akan menggunakannya untuk dengan cepat menemukan satu ujung, lalu melintasi ke yang lain. Ini paling efisien.
Setiap MENJELASKAN yang saya lihat menunjukkan "IN (...)" dan "... ATAU ..." yang dapat dipertukarkan dan sama-sama efisien. Yang Anda harapkan, karena pengoptimal tidak memiliki cara untuk mengetahui apakah mereka terdiri dari interval. Ini juga setara dengan UNION ALL SELECT pada nilai-nilai individual.
sumber
Seperti yang dijelaskan oleh orang lain, IN lebih baik dipilih daripada ATAU sehubungan dengan kinerja permintaan.
Pertanyaan dengan kondisi ATAU mungkin membutuhkan waktu eksekusi lebih lama dalam kasus di bawah ini.
sumber