Apakah ada peningkatan kinerja dalam mengindeks bidang boolean?


103

Saya baru saja akan menulis kueri yang menyertakan WHERE isok=1. Sesuai dengan namanya, isokadalah bidang boolean (sebenarnya TINYINT(1) UNSIGNEDyang disetel ke 0 atau 1 sesuai kebutuhan).

Apakah ada peningkatan kinerja dalam mengindeks bidang ini? Akankah mesin (InnoDB dalam kasus ini) berkinerja lebih baik atau lebih buruk saat mencari indeks?


Jawaban:


80

Tidak juga. Anda harus memikirkannya seperti sebuah buku. Jika hanya ada 3 jenis kata dalam sebuah buku dan Anda mengindeks semuanya, Anda akan memiliki jumlah halaman indeks yang sama dengan halaman biasa.

Akan ada peningkatan kinerja jika hanya ada sedikit catatan dengan satu nilai. Misalnya, jika Anda memiliki 1000 record dan 10 di antaranya BENAR, maka akan berguna jika Anda mencari denganisok = 1

Seperti yang disebutkan Michael Durrant, ini juga membuat penulisan menjadi lebih lambat.

EDIT: Kemungkinan duplikasi: Mengindeks bidang boolean

Di sini dijelaskan bahwa meskipun Anda memiliki indeks, jika Anda memiliki terlalu banyak catatan, ia tidak menggunakan indeks. MySQL tidak menggunakan indeks saat memeriksa = 1, tetapi menggunakannya dengan = 0


4
Sepertinya itu "ya: 2 - tidak: 1". Ada yang salah di sini, tapi siapa?
Niet the Dark Absol

4
Ini tidak sepenuhnya benar, tanpa indeks mySql perlu memindai seluruh tabel untuk menemukan baris yang relevan.
ilanco

4
jika tidak maka akan memindai seluruh indeks. (yang sama panjangnya dalam banyak kasus)
Michael Koper

1
Itu bisa membuat perbedaan. Potong saja waktu eksekusi menjadi setengah dari kueri hanya dengan menambahkan indeks, dan penulisan jarang terjadi dan cukup murah sehingga kami tidak terlalu peduli dengan hukumannya. Seperti segala sesuatu, jangan berasumsi, ukur (juga karena database tidak selalu benar-benar berperilaku seperti yang Anda harapkan secara logis)
Eelco

6
Ini mengasumsikan distribusi yang sama antara TRUE dan FALSE. Seperti yang disebutkan oleh @oucil di bawah ini, jika Anda mencari nilai boolean yang terbilang langka, mungkin perlu waktu agak lama. Tidak mengatakan Anda harus selalu mengindeks, tetapi saya akan menganggap sifat data dan kueri Anda juga penting di sebagian besar mesin database.
mahemoff

118

Hanya untuk memberikan poin yang lebih baik pada beberapa jawaban lain di sini, karena menurut pengalaman saya, mereka yang melihat pertanyaan seperti ini berada di perahu yang sama dengan kita, kita semua pernah mendengar bahwa mengindeks bidang Boolean tidak ada gunanya, namun ...

Kami memiliki tabel dengan sekitar 4 juta baris, hanya sekitar 1000 atau lebih pada satu waktu sakelar Boolean ditandai dan itulah yang kami telusuri. Menambahkan indeks pada bidang Boolean kami mempercepat kueri berdasarkan urutan besarnya, dari sekitar 9+ detik menjadi sepersekian detik.


Ya, sementara Anda harus secara definitif mencoba memahami 'mengapa' hal-hal, selalu mengukur bersama dan mencoba hal-hal yang berbeda pada dataset Anda yang sebenarnya untuk melihat apakah teori Anda cocok dengan perilaku aktual mesin db (Anda akan terkejut ... )
Eelco

8
@Eelco Anda benar, tetapi dalam kasus ini, hasilnya benar-benar sesuai dengan teori dasar. Ide dasar bahwa ini harus diabaikan hanya masuk akal jika Anda sekitar 50% cenderung menemukan item yang cocok dengan pencarian Anda. Kemudian, untuk menemukan 100 pertandingan, DB perlu mengulang 200 item. Tetapi jika item hanya cocok 1% dari waktu, itu perlu mengulang 10.000 item.
mahemoff

7
Saya suka ketika orang benar-benar mencoba sesuatu di lapangan dan memberikan umpan balik perolehan kinerja daripada hanya berfilsafat.
Viktor Joras

WHERE my_col > 0 bukannya my_col = 1juga tampaknya membantu kecepatan
Aaron

28

Itu tergantung pada kueri aktual dan selektivitas kombinasi indeks / kueri.

Kasus A : kondisi WHERE isok = 1dan tidak ada yang lain di sana:

SELECT *
FROM tableX
WHERE isok = 1
  • Jika indeks cukup selektif (katakanlah Anda memiliki 1 juta baris dan hanya 1k yang memilikinya isok = 1), maka mesin SQL mungkin akan menggunakan indeks dan menjadi lebih cepat daripada tanpa itu.

  • Jika indeks tidak cukup selektif (katakanlah Anda memiliki 1 juta baris dan lebih dari 100k memilikinya isok = 1), maka mesin SQL mungkin tidak akan menggunakan indeks dan melakukan pemindaian tabel.

Kasus B : kondisi WHERE isok = 1dan lebih banyak barang:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Kemudian, itu tergantung pada indeks lain yang Anda miliki. Indeks pada another_columnmungkin akan lebih selektif daripada indeks isokyang hanya memiliki dua kemungkinan nilai. Indeks (another_column, isok)atau (isok, another_column)bahkan lebih baik.


Menurut saya, ini adalah jawaban yang lebih tepat dibandingkan dengan jawaban teratas. juga distribusi data.
tyan

12

Itu tergantung pada distribusi datanya.

Bayangkan saya memiliki sebuah buku dengan 1000 halaman yang diketik dengan cermat, dan satu-satunya kata dalam buku saya adalah 'ya' dan 'tidak' yang diulang berulang-ulang dan didistribusikan secara acak. Jika saya diminta untuk melingkari semua contoh 'ya', apakah indeks di belakang buku membantu? Tergantung.

Jika ada distribusi acak setengah-setengah dari ya dan tidak, mencari di indeks tidak akan membantu. Indeks akan membuat buku jauh lebih besar, dan bagaimanapun saya akan lebih cepat memulai dari depan dan menelusuri setiap halaman mencari semua contoh 'ya' dan memutarnya, daripada mencari setiap item di indeks dan kemudian mengambil referensi dari entri indeks ke halaman yang diacunya.

Tetapi jika ada, katakanlah, hanya sepuluh contoh 'ya' dalam buku seribu halaman saya dan yang lainnya hanya jutaan tidak, maka indeks akan menghemat banyak waktu untuk menemukan sepuluh contoh 'ya' dan memutarnya .

Itu sama di database. Jika itu adalah distribusi 50:50, maka indeks tidak akan membantu - mesin database lebih baik hanya membajak data dari awal hingga akhir (pemindaian tabel lengkap), dan indeks hanya akan membuat database lebih besar, dan lebih lambat untuk menulis dan memperbarui. Tetapi jika itu adalah sesuatu seperti distribusi 4000: 1 (sesuai oucil di utas ini), maka pencarian indeks dapat mempercepatnya sangat, jika 1 dari 4000 item yang Anda cari.


5

Tidak, biasanya tidak.

Anda biasanya mengindeks bidang untuk mencari ketika mereka memiliki selektivitas / kardinalitas tinggi. Kardinalitas bidang boolean sangat rendah di sebagian besar tabel. Ini juga akan membuat penulisan Anda sedikit lebih lambat.


3

Sebenarnya ini tergantung pada kueri yang Anda jalankan. Tapi, umumnya ya, serta mengindeks bidang jenis lainnya.


2

Ya indeks akan meningkatkan kinerja, periksa keluaran JELASKAN dengan dan tanpa indeks.

Dari dokumen:

Indeks digunakan untuk menemukan baris dengan nilai kolom tertentu dengan cepat. Tanpa indeks, MySQL harus dimulai dengan baris pertama dan kemudian membaca seluruh tabel untuk menemukan baris yang relevan. Semakin besar tabelnya, semakin banyak biayanya. Jika tabel memiliki indeks untuk kolom yang dimaksud, MySQL dapat dengan cepat menentukan posisi yang dicari di tengah file data tanpa harus melihat semua data.

Menurut saya juga aman untuk mengatakan indeks tidak akan MENURUNKAN kinerja dalam kasus ini, jadi Anda hanya perlu mendapatkan keuntungan darinya.


2
Sebuah indeks memberikan banyak data pada harddisk dan membuat penulisan lebih lambat sehingga Anda tidak hanya mendapatkan keuntungan darinya.
Michael Koper

1
Benar, tetapi dalam kasus ini, TINYINT(1) UNSIGNEDkolom, ukuran datanya akan kecil.
ilanco

Dan overhead tulis tambahan mungkin cukup rendah
Eelco

Bukankah ukuran indeks akan bertambah dengan jumlah baris yang dituju, bukan hanya ukuran bidang yang diindeks?
poolie
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.