Katakanlah saya memiliki hubungan 1-ke-N (person_id, pet_id)
. Saya punya tabel di mana pet_id
kunci utama.
Saya mengerti bahwa indeks sekunder InnoDB pada dasarnya adalah B-tree di mana nilainya adalah nilai kunci primer yang sesuai untuk baris tersebut.
Sekarang, misalkan satu orang dapat memiliki ribuan hewan peliharaan dan saya sering menginginkan hewan peliharaan seseorang pet_id
. Maka akan menjadi masalah jika catatan dalam indeks sekunder diurutkan berdasarkan (person_id, pet_id)
atau hanya person_id
dengan pet_id
's untuk itu person_id
tidak disortir. Menebak nanti.
Jadi, jika person_id
tidak unik, apakah rekaman secara fisik diurutkan berdasarkan (person_id, pet_id)
atau HANYA pet_id
?
Terima kasih
mysql
innodb
primary-key
clustered-index
pengguna3391564
sumber
sumber
person_id
tidak unik, apakah catatan secara fisik disortir oleh(person_id, pet_id)
atau HANYAperson_id
?"Jawaban:
Tidak. Jika tabel Anda memiliki mesin InnoDB dan
PRIMARY KEY
itu(pet_id)
, maka mendefinisikan indeks sekunder sebagai(person_id)
atau(person_id, pet_id)
tidak ada bedanya.Indeks juga menyertakan
pet_id
kolom sehingga nilai diurutkan seperti(person_id, pet_id)
dalam kedua kasus.Kueri seperti yang Anda miliki:
Anda hanya perlu mengakses indeks untuk mendapatkan nilai dan bahkan lebih, itu tidak perlu melakukan apa pun, karena
pet_id
nilai sudah diurutkan dalam indeks. Anda dapat memverifikasi ini dengan melihat rencana eksekusi (EXPLAIN
):Pertama, kami mencoba dengan tabel MyISAM:
Perhatikan filesort!
Sekarang, MyISAM dengan indeks komposit:
Filesort hilang , seperti yang diharapkan.
Sekarang mari kita coba hal yang sama dengan mesin InnoDB:
Juga tidak ada filesort! Meskipun indeks tidak secara eksplisit memiliki
pet_id
kolom, nilainya ada di sana dan diurutkan. Anda dapat memeriksa bahwa jika Anda mendefinisikan indeks dengan(person_id, pet_id)
,EXPLAIN
identik.Mari kita benar-benar melakukannya, dengan InnoDB dan indeks komposit:
Rencana identik dengan kasus sebelumnya.
Agar 100% yakin, saya juga menjalankan 2 case terakhir (mesin InnoDB, dengan indeks tunggal dan komposit) memungkinkan
file_per_table
pengaturan dan menambahkan beberapa ribu baris dalam tabel:Dalam kedua kasus, memeriksa ukuran file aktual, menghasilkan hasil yang identik :
sumber
(<some_column>)
dan(<some_column>, <pk>)
karenaON (<some_column>)
setara denganON (<some_column>) INCLUDE (<pk>)
dan tidakON (<some_column>, <pk>)
. Dalam kebanyakan situasi ini memiliki signifikansi nol, tetapi jika PK Anda acak (yaitu UUID) makaON (<s_c>,<pk>)
dapat menyebabkan fragmentasi tambahan atau jika PK Anda bermakna selain menjadi kunci dan Anda mungkinORDER BY s_c, pk
kemudian jenis seperti itu akan lebih cepat sebagai indeks sudah dalam urutan penuh.INCLUDE (columns)
fungsi. Itu alasan lain saya menyimpulkan bahwa(s_c)
indeks ini setara dengan(s_c, pk)
.Menurut Dokumentasi MySQL tentang Indeks Clustered dan Secondary
Oleh karena itu, menambahkan KUNCI UTAMA ke indeks sekunder jelas berlebihan. Entri indeks Anda ingin
(person_id, pet_id, pet_id)
. Ini juga akan mengasapi indeks sekunder dengan memiliki 2 salinanPRIMARY KEY
.Untuk indeks dengan
(person_id)
, jika Anda menjalankan kueri seperti iniThe
PRIMARY KEY
akan terlibat penuh dalam query ini dan menghasilkan hasil diperintahkan olehPRIMARY KEY
pula. Dari sudut pandang fisik, baris dipesan dengan urutan penyisipan. Jika pet_id adalah AUTO_INCREMENT, maka itu dipesan berdasarkan nomor otomatis.sumber
(owner_id, pet_id)
tetapi Anda dapat membuat kunci(vet_id, pet_id[, owner_id])
untuk memanfaatkan urutan kolom yang berbeda.Kiat 1:
sangat valid. Ini memiliki keunggulan kinerja menjadi lebih efisien ketika banyak permintaan perlu menemukan beberapa baris
WHERE x = 123
. Artinya, itu sedikit lebih efisien daripada yang 'jelas'Satu-satunya aturan tentang
AUTO_INCREMENT
(untuk InnoDB) adalah yangid
harus menjadi kolom pertama dalam beberapa indeks. Perhatikan bahwa aturan yang mengatakan apa-apa tentangPRIMARY
atauUNIQUE
atau 'hanya kolom'.Tip berguna untuk meja besar yang sering diambil
x
bersama dengan barang-barang lainnya.Tips 2: Misalkan Anda punya
Ini adalah indeks "meliputi":
Artinya, seluruh permintaan dapat dilakukan di dalam indeks BTree. EXPLAIN akan mengatakan "Menggunakan indeks".
sumber