Mengapa MySQL tidak menggunakan indeks pada bidang int yang digunakan sebagai boolean?

select * from myTable where myInt

tidak akan menampilkan kemungkinan_kunci apa pun saat menjelaskan kueri meskipun ada indeks di bidang myInt.

Sunting:
Indeks yang dipermasalahkan tidak unik.


person Senseful    schedule 24.12.2008    source sumber


Jawaban (4)


Agar MySQL dapat menggunakan indeks, Anda harus secara eksplisit membandingkan bidang int dengan suatu nilai (misalnya true, 1).

select * from myTable where myInt = true
person Senseful    schedule 24.12.2008

Saya bukan ahli basis data, tetapi bukankah itu menggagalkan tujuan memiliki indeks di lapangan jika hanya ada dua kemungkinan nilai bidang tersebut?

Jika semua bidang dalam kolom yang diindeks adalah unik, maka mesin database dapat melakukan pemindaian indeks untuk menemukan baris yang relevan. Jika hanya ada dua nilai yang mungkin - maka saya tidak melihat tujuan mengindeks bidang itu. Mesin DB harus melakukan operasi yang sama seperti jika indeks tidak ada.

Mungkin MySQL tidak menampilkannya sebagai kunci yang mungkin karena mesin telah membuang gagasan untuk menggunakan indeks dalam rencana eksekusi?

person matt b    schedule 24.12.2008
comment
Indeks tidak dibatasi pada kolom unik. Indeks pada dasarnya mencari tabel yang mengurutkan/hash berdasarkan kolom dalam indeks. Tujuan dari indeks adalah untuk memberitahu RDMS untuk mengoptimalkan pencarian kolom tertentu dalam sebuah tabel. Indeks pada bools mungkin tidak berpengaruh banyak terhadap kinerja, namun valid. - person Bernard Igiri; 24.12.2008
comment
Benar, saya tidak menanyakan valid atau tidak, saya bertanya apakah bermanfaat. Bidang yang diindeks hanya akan bernilai 0 atau 1, sehingga indeks akan berisi dua entri, masing-masing dengan N/2 baris di dalamnya dengan N = ukuran tabel. Benar? Jadi apa gunanya mengindeks bidang ini? - person matt b; 24.12.2008
comment
@matt b: Kardinalitas tidak menentukan kekhususan. Misalkan bidang tersebut hanya disetel ke 1 dalam waktu yang sangat singkat: Jika seseorang tertarik untuk memilih hanya baris-baris tersebut maka pemindaian tabel penuh akan menjadi konyol. - person user359996; 07.03.2012

Ada banyak faktor yang perlu dipertimbangkan.

Salah satu faktor yang tidak boleh dimasukkan ke dalamnya adalah notasi yang digunakan dalam soal. Jika kolomnya adalah boolean, maka kondisi ini harus diperlakukan sama oleh pengoptimal:

SELECT * FROM MyTable WHERE MyInt;

SELECT * FROM MyTable WHERE MyInt != 0;

SELECT * FROM MyTable WHERE MyInt IS TRUE;

SELECT * FROM MyTable WHERE MyInt = TRUE;

Mungkin ada formulasi lain yang setara. Yang pertama bukan SQL standar (walaupun jenis MyInt adalah BOOLEAN; yang lain adalah standar. Namun pengoptimal harus mengubah singkatan menjadi bentuk panjang yang sesuai dan kemudian berperilaku sama seolah-olah bentuk panjang itu ditulis oleh pengguna. (Jika pengoptimal tidak melakukan hal ini, bisa dibilang ada masalah dengan pengoptimal; kueri harus direduksi menjadi bentuk kanonik sebelum memutuskan cara memproses kueri. Namun, sering kali terdapat titik buta bahkan pada pengoptimal terbaik sekalipun (Mempelajari cara menghindari hal tersebut adalah suatu bentuk seni, dan secara inheren spesifik untuk DBMS.)

Pengoptimal menggunakan indeks ketika ia yakin indeks tersebut akan meningkatkan kinerja kueri. Jika indeks tidak meningkatkan kinerja, indeks akan diabaikan (jika pengoptimalnya bagus). Terkadang, hal ini bergantung pada apakah statistik indeks tersebut mutakhir.

Dalam sistem pergudangan data, sistem dapat dirancang dan dikonfigurasi untuk melakukan pemindaian tabel secara berurutan dengan sangat cepat; dalam sistem seperti itu, jika selektivitas suatu indeks sedemikian rupa sehingga penggunaannya akan menarik lebih dari 25% baris, sebenarnya akan lebih cepat untuk melakukan pemindaian tabel penuh daripada menggunakan indeks.

Pikirkan tentang itu. Saat membaca melalui indeks, DBMS harus melakukan setidaknya dua kali pembacaan; ia membaca informasi tentang baris dari halaman indeks, dan kemudian harus membaca baris dari halaman data.

Beberapa DBMS menyediakan tabel indeks saja. Semua data ada di indeks. DBMS lain menyediakan mekanisme sehingga Anda dapat mengatakan "indeks unik pada kolom A, B, C; namun, sertakan kolom D dan E juga dalam data". Lalu jika query membutuhkan data dari A, B, C, D atau E (atau kombinasi apapun) dan tidak ada pemfilteran pada kolom lain, DBMS hanya perlu memindai indeksnya, bukan halaman tabelnya juga.

Biasanya, Anda mendapatkan banyak baris indeks dalam satu halaman. Namun, untuk beberapa tabel, membaca indeks mungkin memerlukan membaca lebih banyak data daripada membaca baris. Pertimbangkan tabel pemetaan pola dasar banyak-ke-banyak yang berisi dua nilai ID bilangan bulat (4-byte). Hal ini memerlukan 8 byte per baris pada halaman data, namun indeks mungkin memerlukan overhead 4-8 byte (karena entri kunci indeks menyimpan dua nilai ID ditambah informasi yang diperlukan untuk menemukan baris terkait pada disk). Jadi, pemindaian indeks mungkin melibatkan I/O disk dua kali lebih banyak daripada pemindaian data, meskipun pemindaian indeks dilakukan 'hanya indeks'.

Ini hampir tidak menyentuh permukaan kemungkinan alasan untuk menggunakan atau tidak menggunakan indeks.

person Jonathan Leffler    schedule 24.12.2008

Bagi saya, format SQL pertanyaan Anda tampak salah. Apakah Anda mencari nilai kolom yang bukan nol? Ini harus menggunakan indeks:

select * from myTable where myInt is not null
person Kieveli    schedule 24.12.2008
comment
MySQL mengevaluasi ekspresi bukan nol/null sebagai benar, jadi misalnya pernyataan SELECT * FROM myTable WHERE 1 adalah pernyataan yang valid dan akan mengembalikan semua catatan dari tabel. Di bidang myInt, saya menyimpan nilai 0 atau 1, bukan nilai NULL dan BUKAN NULL. - person Senseful; 24.12.2008
comment
@eagle: Anda menyimpan dua nilai bukan nol yang berbeda (0 dan 1). Dan MySQL mengizinkan Anda menggunakan singkatan non-standar; SQL Anda tidak akan bermigrasi ke DBMS lain dengan mudah jika Anda menggunakan singkatannya. - person Jonathan Leffler; 24.12.2008