Performa sangat penting di banyak produk konsumen seperti e-commerce, sistem pembayaran, game, aplikasi transportasi, dan sebagainya. Meskipun basis data dioptimalkan secara internal melalui berbagai mekanisme untuk memenuhi persyaratan kinerjanya di dunia modern, banyak yang bergantung pada pengembang aplikasi juga — lagipula, hanya pengembang yang tahu kueri apa yang harus dijalankan aplikasi.
Pengembang yang berurusan dengan database relasional telah menggunakan atau setidaknya mendengar tentang pengindeksan, dan ini adalah konsep yang sangat umum di dunia database. Namun, bagian terpenting adalah memahami apa yang akan diindeks &bagaimana pengindeksan akan meningkatkan waktu respons kueri. Untuk melakukan itu, Anda perlu memahami bagaimana Anda akan menanyakan tabel database Anda. Indeks yang tepat hanya dapat dibuat jika Anda tahu persis seperti apa kueri &pola akses data Anda.
Dalam terminologi sederhana, indeks memetakan kunci pencarian ke data yang sesuai pada disk dengan menggunakan struktur data di dalam memori &di disk yang berbeda. Indeks digunakan untuk mempercepat pencarian dengan mengurangi jumlah record yang akan dicari.
Sebagian besar indeks dibuat pada kolom yang ditentukan dalam WHERE
klausa kueri saat database mengambil &memfilter data dari tabel berdasarkan kolom tersebut. Jika Anda tidak membuat indeks, database memindai semua baris, memfilter baris yang cocok &mengembalikan hasilnya. Dengan jutaan catatan, operasi pemindaian ini mungkin memakan waktu beberapa detik &waktu respons yang tinggi ini membuat API &aplikasi lebih lambat &tidak dapat digunakan. Mari kita lihat contohnya —
Kami akan menggunakan MySQL dengan mesin database InnoDB default, meskipun konsep yang dijelaskan dalam artikel ini kurang lebih sama di server database lain seperti Oracle, MSSQL dll.
Buat tabel bernama index_demo
dengan skema berikut:
CREATE TABLE index_demo (
name VARCHAR(20) NOT NULL,
age INT,
pan_no VARCHAR(20),
phone_no VARCHAR(20)
);
Bagaimana cara memverifikasi bahwa kami menggunakan mesin InnoDB?
Jalankan perintah di bawah ini:
SHOW TABLE STATUS WHERE name = 'index_demo' \G;
Engine
kolom pada tangkapan layar di atas mewakili mesin yang digunakan untuk membuat tabel. Di sini InnoDB
digunakan.
Sekarang Masukkan beberapa data acak ke dalam tabel, tabel saya dengan 5 baris terlihat seperti berikut:
Saya belum membuat indeks apa pun sampai sekarang di tabel ini. Mari kita verifikasi ini dengan perintah:SHOW INDEX
. Ini mengembalikan 0 hasil.
Saat ini, jika kita menjalankan SELECT
simple sederhana kueri, karena tidak ada indeks yang ditentukan pengguna, kueri akan memindai seluruh tabel untuk mengetahui hasilnya:
EXPLAIN SELECT * FROM index_demo WHERE name = 'alex';
EXPLAIN
menunjukkan bagaimana mesin kueri berencana untuk mengeksekusi kueri. Pada tangkapan layar di atas, Anda dapat melihat bahwa rows
kolom mengembalikan 5
&possible_keys
mengembalikan null
. possible_keys
mewakili semua indeks yang tersedia yang dapat digunakan dalam kueri ini. key
kolom mewakili indeks mana yang sebenarnya akan digunakan dari semua kemungkinan indeks dalam kueri ini.
Kunci Utama:
Permintaan di atas sangat tidak efisien. Mari optimalkan kueri ini. Kami akan membuat phone_no
kolom a PRIMARY KEY
dengan asumsi bahwa tidak ada dua pengguna yang dapat ada di sistem kami dengan nomor telepon yang sama. Pertimbangkan hal-hal berikut saat membuat kunci utama:
- Kunci utama harus menjadi bagian dari banyak kueri penting dalam aplikasi Anda.
- Kunci utama adalah batasan yang secara unik mengidentifikasi setiap baris dalam sebuah tabel. Jika beberapa kolom merupakan bagian dari kunci utama, kombinasi tersebut harus unik untuk setiap baris.
- Kunci utama harus Non-null. Jangan pernah menjadikan bidang yang dapat dibatalkan sebagai kunci utama Anda. Dengan standar ANSI SQL, kunci utama harus dapat dibandingkan satu sama lain, dan Anda pasti dapat mengetahui apakah nilai kolom kunci utama untuk baris tertentu lebih besar, lebih kecil, atau sama dengan baris lainnya. Sejak
NULL
berarti nilai yang tidak ditentukan dalam standar SQL, Anda tidak dapat secara deterministik membandingkanNULL
dengan nilai lain, jadi secara logisNULL
tidak diperbolehkan. - Jenis kunci utama yang ideal harus berupa angka seperti
INT
atauBIGINT
karena perbandingan bilangan bulat lebih cepat, jadi melintasi indeks akan sangat cepat.
Seringkali kita mendefinisikan sebuah id
bidang sebagai AUTO INCREMENT
dalam tabel &gunakan itu sebagai kunci utama, tetapi pilihan kunci utama bergantung pada pengembang.
Bagaimana jika Anda tidak membuat kunci utama sendiri?
Anda tidak wajib membuat kunci utama sendiri. Jika Anda belum menentukan kunci utama apa pun, InnoDB secara implisit membuatnya untuk Anda karena InnoDB secara desain harus memiliki kunci utama di setiap tabel. Jadi, setelah Anda membuat kunci utama nanti untuk tabel itu, InnoDB menghapus kunci utama yang ditentukan secara otomatis sebelumnya.
Karena kita tidak memiliki kunci utama yang ditentukan sampai sekarang, mari kita lihat apa yang dibuat InnoDB secara default untuk kita:
SHOW EXTENDED INDEXES FROM index_demo;
EXTENDED
menunjukkan semua indeks yang tidak dapat digunakan oleh pengguna tetapi dikelola sepenuhnya oleh MySQL.
Di sini kita melihat bahwa MySQL telah mendefinisikan indeks komposit (kita akan membahas indeks komposit nanti) pada DB_ROW_ID
, DB_TRX_ID
, DB_ROLL_PTR
, &semua kolom yang ditentukan dalam tabel. Dengan tidak adanya kunci utama yang ditentukan pengguna, indeks ini digunakan untuk menemukan catatan secara unik.
Apa perbedaan antara kunci &indeks?
Meskipun istilah key
&index
digunakan secara bergantian, key
berarti kendala yang dikenakan pada perilaku kolom. Dalam hal ini, batasannya adalah bahwa kunci utama adalah bidang yang tidak dapat dibatalkan yang secara unik mengidentifikasi setiap baris. Sebaliknya, index
adalah struktur data khusus yang memfasilitasi pencarian data di seluruh tabel.
Sekarang mari kita buat indeks utama di phone_no
&periksa indeks yang dibuat:
ALTER TABLE index_demo ADD PRIMARY KEY (phone_no);
SHOW INDEXES FROM index_demo;
Perhatikan bahwa CREATE INDEX
tidak dapat digunakan untuk membuat indeks utama, tetapi ALTER TABLE
digunakan.
Pada tangkapan layar di atas, kita melihat bahwa satu indeks utama dibuat pada kolom phone_no
. Kolom dari gambar berikut dijelaskan sebagai berikut:
Table
:Tabel tempat indeks dibuat.
Non_unique
:Jika nilainya 1, indeksnya tidak unik, jika nilainya 0, indeksnya unik.
Key_name
:Nama indeks yang dibuat. Nama indeks utama selalu PRIMARY
di MySQL, terlepas dari apakah Anda telah memberikan nama indeks atau tidak saat membuat indeks.
Seq_in_index
:Nomor urut kolom dalam indeks. Jika beberapa kolom merupakan bagian dari indeks, nomor urut akan ditetapkan berdasarkan cara kolom diurutkan selama waktu pembuatan indeks. Nomor urut dimulai dari 1.
Collation
:bagaimana kolom diurutkan dalam index. A
artinya naik, D
berarti turun, NULL
berarti tidak diurutkan.
Cardinality
:Perkiraan jumlah nilai unik dalam indeks. Lebih banyak kardinalitas berarti semakin tinggi peluang pengoptimal kueri akan memilih indeks untuk kueri.
Sub_part
:Awalan indeks. Ini adalah NULL
jika seluruh kolom diindeks. Jika tidak, ini menunjukkan jumlah byte yang diindeks jika kolom diindeks sebagian. Kami akan menentukan indeks parsial nanti.
Packed
:Menunjukkan bagaimana kunci dikemas; NULL
jika tidak.
Null
:YES
jika kolom mungkin berisi NULL
nilai dan kosongkan jika tidak.
Index_type
:Menunjukkan struktur data pengindeksan mana yang digunakan untuk indeks ini. Beberapa kandidat yang mungkin adalah — BTREE
, HASH
, RTREE
, atau FULLTEXT
.
Comment
:Informasi tentang indeks tidak dijelaskan dalam kolomnya sendiri.
Index_comment
:Komentar untuk indeks yang ditentukan saat Anda membuat indeks dengan COMMENT
atribut.
Sekarang mari kita lihat apakah indeks ini mengurangi jumlah baris yang akan ditelusuri untuk phone_no
yang diberikan di WHERE
klausa kueri.
EXPLAIN SELECT * FROM index_demo WHERE phone_no = '9281072002';
Dalam cuplikan ini, perhatikan bahwa rows
kolom telah mengembalikan 1
hanya possible_keys
&key
keduanya mengembalikan PRIMARY
. Jadi pada dasarnya berarti menggunakan indeks utama bernama PRIMARY
(nama ditetapkan secara otomatis saat Anda membuat kunci utama), pengoptimal kueri langsung masuk ke catatan &mengambilnya. Ini sangat efisien. Inilah tepatnya kegunaan indeks — untuk meminimalkan cakupan pencarian dengan mengorbankan ruang ekstra.
Indeks Tergugus:
Sebuah clustered index
ditempatkan dengan data dalam ruang tabel yang sama atau file disk yang sama. Anda dapat menganggap bahwa indeks berkerumun adalah B-Tree
indeks yang simpul daunnya adalah blok data aktual pada disk, karena indeks &data berada bersama. Jenis indeks ini secara fisik mengatur data pada disk sesuai urutan logis dari kunci indeks.
Apa yang dimaksud dengan organisasi data fisik?
Secara fisik, data diatur pada disk di ribuan atau jutaan blok disk/data. Untuk indeks berkerumun, itu tidak wajib bahwa semua blok disk disimpan secara menular. Blok data fisik selalu dipindahkan ke sana-sini oleh OS kapan pun diperlukan. Sebuah sistem database tidak memiliki kontrol mutlak atas bagaimana ruang data fisik dikelola, tetapi di dalam blok data, catatan dapat disimpan atau dikelola dalam urutan logis dari kunci indeks. Diagram sederhana berikut menjelaskannya:
- Persegi panjang besar berwarna kuning mewakili blok disk / blok data
- persegi panjang berwarna biru mewakili data yang disimpan sebagai baris di dalam blok tersebut
- area footer mewakili indeks blok tempat persegi panjang kecil berwarna merah berada dalam urutan kunci tertentu yang diurutkan. Blok kecil ini tidak lain adalah semacam penunjuk yang menunjuk ke offset catatan.
Catatan disimpan di blok disk dalam urutan arbitrer apa pun. Setiap kali catatan baru ditambahkan, catatan tersebut akan ditambahkan di ruang berikutnya yang tersedia. Setiap kali catatan yang ada diperbarui, OS memutuskan apakah catatan itu masih dapat masuk ke posisi yang sama atau posisi baru harus dialokasikan untuk catatan itu.
Jadi posisi catatan sepenuhnya ditangani oleh OS &tidak ada hubungan pasti antara urutan dua catatan. Untuk mengambil catatan dalam urutan logis kunci, halaman disk berisi bagian indeks di footer, indeks berisi daftar pointer offset dalam urutan kunci. Setiap kali record diubah atau dibuat, indeksnya disesuaikan.
Dengan cara ini, Anda benar-benar tidak perlu peduli untuk benar-benar mengatur catatan fisik dalam urutan tertentu, melainkan bagian indeks kecil dipertahankan dalam urutan itu &mengambil atau memelihara catatan menjadi sangat mudah.
Keuntungan Indeks Tergugus:
Pemesanan atau co-lokasi data terkait ini sebenarnya membuat indeks berkerumun lebih cepat. Saat data diambil dari disk, blok lengkap yang berisi data dibaca oleh sistem karena sistem IO disk kami menulis &membaca data dalam blok. Jadi dalam hal kueri rentang, sangat mungkin bahwa data yang dikumpulkan di-buffer di memori. Katakanlah Anda menjalankan kueri berikut:
SELECT * FROM index_demo WHERE phone_no > '9010000000' AND phone_no < '9020000000'
Sebuah blok data diambil dalam memori ketika query dijalankan. Katakanlah blok data berisi phone_no
dalam kisaran dari 9010000000
ke 9030000000
. Jadi rentang apa pun yang Anda minta dalam kueri hanyalah sebagian dari data yang ada di blok. Jika sekarang Anda menjalankan kueri berikutnya untuk mendapatkan semua nomor telepon dalam jangkauan, katakan dari 9015000000
ke 9019000000
, Anda tidak perlu mengambil blok lagi dari disk. Data lengkap dapat ditemukan di blok data saat ini, sehingga clustered_index
mengurangi jumlah IO disk dengan mengumpulkan data terkait sebanyak mungkin dalam blok data yang sama. IO disk yang berkurang ini menyebabkan peningkatan kinerja.
Jadi, jika Anda memikirkan kunci utama dengan baik &kueri Anda didasarkan pada kunci utama, kinerjanya akan sangat cepat.
Batasan Indeks Tergugus:
Karena indeks berkerumun memengaruhi organisasi fisik data, hanya ada satu indeks berkerumun per tabel.
Hubungan antara Primary Key &Indeks Clustered:
Anda tidak dapat membuat indeks berkerumun secara manual menggunakan InnoDB di MySQL. MySQL memilihnya untuk Anda. Tapi bagaimana cara memilihnya? Kutipan berikut berasal dari dokumentasi MySQL:
Saat Anda menentukanPRIMARY KEY
di meja Anda,InnoDB
menggunakannya sebagai indeks berkerumun. Tentukan kunci utama untuk setiap tabel yang Anda buat. Jika tidak ada kolom unik dan non-null logis atau kumpulan kolom, tambahkan kolom kenaikan otomatis baru, yang nilainya diisi secara otomatis.
Jika Anda tidak mendefinisikanPRIMARY KEY
untuk tabel Anda, MySQL menempatkanUNIQUE
pertama indeks di mana semua kolom kunciNOT NULL
danInnoDB
menggunakannya sebagai indeks berkerumun.
Jika tabel tidak memilikiPRIMARY KEY
atauUNIQUE
yang sesuai indeks,InnoDB
secara internal menghasilkan indeks berkerumun tersembunyi bernamaGEN_CLUST_INDEX
pada kolom sintetis yang berisi nilai ID baris. Baris diurutkan berdasarkan ID yangInnoDB
menetapkan ke baris dalam tabel seperti itu. ID baris adalah bidang 6-byte yang meningkat secara monoton saat baris baru dimasukkan. Dengan demikian, baris yang diurutkan oleh ID baris secara fisik berada dalam urutan penyisipan.
Singkatnya, mesin MySQL InnoDB sebenarnya mengelola indeks utama sebagai indeks berkerumun untuk meningkatkan kinerja, sehingga kunci utama &catatan aktual pada disk dikelompokkan bersama.
Struktur Indeks kunci Primer (berkelompok):
Sebuah indeks biasanya dipertahankan sebagai Pohon B+ pada disk &di dalam memori, dan indeks apa pun disimpan dalam blok-blok pada disk. Blok ini disebut blok indeks. Entri di blok indeks selalu diurutkan pada indeks/kunci pencarian. Blok indeks daun dari indeks berisi pencari baris. Untuk indeks utama, pencari baris mengacu pada alamat virtual dari lokasi fisik yang sesuai dari blok data pada disk tempat baris berada diurutkan sesuai dengan kunci indeks.
Dalam diagram berikut, persegi panjang sisi kiri mewakili blok indeks tingkat daun, dan persegi panjang sisi kanan mewakili blok data. Logikanya blok data terlihat selaras dalam urutan yang diurutkan, tetapi seperti yang telah dijelaskan sebelumnya, lokasi fisik sebenarnya mungkin tersebar di sana-sini.
Apakah mungkin membuat indeks utama pada kunci non-utama?
Di MySQL, indeks utama dibuat secara otomatis, dan kami telah menjelaskan di atas bagaimana MySQL memilih indeks utama. Namun di dunia database, sebenarnya tidak perlu membuat indeks pada kolom kunci utama — indeks utama juga dapat dibuat pada kolom non kunci utama. Tetapi ketika dibuat pada kunci utama, semua entri kunci adalah unik dalam indeks, sementara dalam kasus lain, indeks utama mungkin juga memiliki kunci duplikat.
Apakah mungkin untuk menghapus kunci utama?
Dimungkinkan untuk menghapus kunci utama. Saat Anda menghapus kunci utama, indeks berkerumun terkait serta properti keunikan kolom itu akan hilang.
ALTER TABLE `index_demo` DROP PRIMARY KEY;
- If the primary key does not exist, you get the following error:
"ERROR 1091 (42000): Can't DROP 'PRIMARY'; check that column/key exists"
Keuntungan Indeks Utama:
- Kueri rentang berbasis indeks utama sangat efisien. Mungkin ada kemungkinan bahwa blok disk yang telah dibaca database dari disk berisi semua data yang termasuk dalam kueri, karena indeks utama dikelompokkan &rekaman diurutkan secara fisik. Jadi lokasi data dapat disediakan oleh indeks utama.
- Kueri apa pun yang memanfaatkan kunci utama sangat cepat.
Kerugian Indeks Utama:
- Karena indeks utama berisi referensi langsung ke alamat blok data melalui ruang alamat virtual &blok disk secara fisik diatur dalam urutan kunci indeks, setiap kali OS melakukan pemisahan halaman disk karena
DML
operasi sepertiINSERT
/UPDATE
/DELETE
, indeks utama juga perlu diperbarui. JadiDML
operasi memberi tekanan pada kinerja indeks utama.
Indeks Sekunder:
Setiap indeks selain indeks berkerumun disebut indeks sekunder. Indeks sekunder tidak memengaruhi lokasi penyimpanan fisik tidak seperti indeks utama.
Kapan Anda memerlukan Indeks Sekunder?
Anda mungkin memiliki beberapa kasus penggunaan dalam aplikasi Anda di mana Anda tidak menanyakan database dengan kunci utama. Dalam contoh kami phone_no
adalah kunci utama tetapi kita mungkin perlu menanyakan database dengan pan_no
, atau name
. Dalam kasus seperti itu, Anda memerlukan indeks sekunder pada kolom ini jika frekuensi kueri tersebut sangat tinggi.
Bagaimana cara membuat indeks sekunder di MySQL?
Perintah berikut membuat indeks sekunder di name
kolom di index_demo
tabel.
CREATE INDEX secondary_idx_1 ON index_demo (name);
Struktur Indeks Sekunder:
Dalam diagram di bawah, persegi panjang berwarna merah mewakili blok indeks sekunder. Indeks sekunder juga dipertahankan di B+ Tree dan diurutkan sesuai kunci di mana indeks dibuat. Node daun berisi salinan kunci dari data yang sesuai dalam indeks utama.
Jadi untuk memahaminya, Anda dapat berasumsi bahwa indeks sekunder memiliki referensi ke alamat kunci utama, meskipun tidak demikian. Mengambil data melalui indeks sekunder berarti Anda harus melintasi dua pohon B+ — satu adalah pohon indeks B+ sekunder itu sendiri, dan yang lainnya adalah pohon indeks B+ utama.
Keuntungan Indeks Sekunder:
Secara logis Anda dapat membuat indeks sekunder sebanyak yang Anda inginkan. Namun pada kenyataannya berapa banyak indeks yang sebenarnya dibutuhkan membutuhkan proses pemikiran yang serius karena setiap indeks memiliki penaltinya sendiri.
Kerugian Indeks Sekunder:
Dengan DML
operasi seperti DELETE
/ INSERT
, indeks sekunder juga perlu diperbarui agar salinan kolom kunci utama dapat dihapus / disisipkan. Dalam kasus seperti itu, keberadaan banyak indeks sekunder dapat menimbulkan masalah.
Juga, jika kunci utama sangat besar seperti URL
, karena indeks sekunder berisi salinan nilai kolom kunci utama, hal itu dapat menjadi tidak efisien dalam hal penyimpanan. Lebih banyak kunci sekunder berarti lebih banyak salinan duplikat dari nilai kolom kunci utama, sehingga lebih banyak penyimpanan jika kunci utama besar. Juga kunci utama itu sendiri menyimpan kunci, sehingga efek gabungan pada penyimpanan akan sangat tinggi.
Pertimbangan sebelum Anda menghapus Indeks Utama:
Di MySQL, Anda dapat menghapus indeks utama dengan menjatuhkan kunci utama. Kita telah melihat bahwa indeks sekunder bergantung pada indeks primer. Jadi, jika Anda menghapus indeks utama, semua indeks sekunder harus diperbarui agar berisi salinan kunci indeks utama baru yang disesuaikan otomatis oleh MySQL.
Proses ini mahal bila ada beberapa indeks sekunder. Juga tabel lain mungkin memiliki referensi kunci asing ke kunci utama, jadi Anda perlu menghapus referensi kunci asing tersebut sebelum Anda menghapus kunci utama.
Ketika kunci utama dihapus, MySQL secara otomatis membuat kunci utama lain secara internal, dan itu adalah operasi yang mahal.
Indeks Kunci UNIK:
Seperti kunci utama, kunci unik juga dapat mengidentifikasi catatan secara unik dengan satu perbedaan — kolom kunci unik dapat berisi null
nilai.
Tidak seperti server database lainnya, di MySQL, kolom kunci unik dapat memiliki null
sebanyak-banyaknya nilai-nilai mungkin. Dalam standar SQL, null
berarti nilai yang tidak ditentukan. Jadi jika MySQL harus berisi hanya satu null
nilai dalam kolom kunci unik, ia harus mengasumsikan bahwa semua nilai nol adalah sama.
Tapi secara logika ini tidak benar karena null
berarti tidak terdefinisi — dan nilai yang tidak terdefinisi tidak dapat dibandingkan satu sama lain, ini adalah sifat dari null
. Karena MySQL tidak dapat menyatakan jika semua null
s artinya sama, memungkinkan beberapa null
nilai di kolom.
Perintah berikut menunjukkan cara membuat indeks kunci unik di MySQL:
CREATE UNIQUE INDEX unique_idx_1 ON index_demo (pan_no);
Indeks Komposit:
MySQL memungkinkan Anda menentukan indeks pada beberapa kolom, hingga 16 kolom. Indeks ini disebut indeks Multi-kolom / Komposit / Majemuk.
Katakanlah kita memiliki indeks yang ditentukan pada 4 kolom — col1
, col2
, col3
, col4
. Dengan indeks komposit, kami memiliki kemampuan pencarian di col1
, (col1, col2)
, (col1, col2, col3)
, (col1, col2, col3, col4)
. Jadi kita bisa menggunakan awalan sisi kiri dari kolom yang diindeks, tapi kita tidak bisa menghilangkan kolom dari tengah &menggunakannya seperti — (col1, col3)
atau (col1, col2, col4)
atau col3
atau col4
dll. Ini adalah kombinasi yang tidak valid.
Perintah berikut membuat 2 indeks komposit di tabel kami:
CREATE INDEX composite_index_1 ON index_demo (phone_no, name, age);
CREATE INDEX composite_index_2 ON index_demo (pan_no, name, age);
Jika Anda memiliki pertanyaan yang berisi WHERE
klausa pada beberapa kolom, tulis klausa dalam urutan kolom indeks komposit. Indeks akan menguntungkan kueri itu. Faktanya, saat memutuskan kolom untuk indeks komposit, Anda dapat menganalisis kasus penggunaan yang berbeda dari sistem Anda &mencoba membuat urutan kolom yang akan menguntungkan sebagian besar kasus penggunaan Anda.
Indeks komposit dapat membantu Anda dalam JOIN
&SELECT
pertanyaan juga. Contoh:di bawah SELECT *
kueri, composite_index_2
digunakan.
Ketika beberapa indeks ditentukan, pengoptimal kueri MySQL memilih indeks yang menghilangkan jumlah baris terbanyak atau memindai baris sesedikit mungkin untuk efisiensi yang lebih baik.
Mengapa kami menggunakan indeks komposit ? Mengapa tidak menentukan beberapa indeks sekunder pada kolom yang kami minati?
MySQL hanya menggunakan satu indeks per tabel per kueri kecuali untuk UNION. (Dalam UNION, setiap kueri logis dijalankan secara terpisah, dan hasilnya digabungkan.) Jadi, mendefinisikan beberapa indeks pada beberapa kolom tidak menjamin indeks tersebut akan digunakan meskipun indeks tersebut merupakan bagian dari kueri.
MySQL memelihara sesuatu yang disebut statistik indeks yang membantu MySQL menyimpulkan seperti apa data dalam sistem. Statistik indeks adalah generalisasi, tetapi berdasarkan meta data ini, MySQL memutuskan indeks mana yang sesuai untuk kueri saat ini.
Bagaimana cara kerja indeks komposit?
Kolom yang digunakan dalam indeks komposit digabungkan bersama, dan kunci gabungan tersebut disimpan dalam urutan yang diurutkan menggunakan B+ Tree. Saat Anda melakukan pencarian, rangkaian kunci pencarian Anda dicocokkan dengan indeks komposit. Kemudian jika ada ketidakcocokan antara urutan kunci pencarian Anda &urutan kolom indeks gabungan, indeks tidak dapat digunakan.
Dalam contoh kami, untuk catatan berikut, kunci indeks komposit dibentuk dengan menggabungkan pan_no
, name
, age
— HJKXS9086Wkousik28
.
+--------+------+------------+------------+
name
age
pan_no
phone_no
+--------+------+------------+------------+
kousik
28
HJKXS9086W
9090909090
Cara mengidentifikasi apakah Anda memerlukan indeks komposit:
- Analisis kueri Anda terlebih dahulu sesuai dengan kasus penggunaan Anda. Jika Anda melihat bidang tertentu muncul bersama dalam banyak kueri, Anda dapat mempertimbangkan untuk membuat indeks gabungan.
- Jika Anda membuat indeks di
col1
&indeks komposit di (col1
,col2
), maka hanya indeks komposit yang akan baik-baik saja.col1
sendiri dapat dilayani oleh indeks komposit itu sendiri karena merupakan awalan sisi kiri dari indeks. - Pertimbangkan kardinalitas. Jika kolom yang digunakan dalam indeks komposit akhirnya memiliki kardinalitas tinggi bersama-sama, mereka adalah kandidat yang baik untuk indeks komposit.
Indeks Cakupan:
Indeks penutup adalah jenis khusus dari indeks komposit di mana semua kolom yang ditentukan dalam kueri di suatu tempat ada di indeks. Jadi pengoptimal kueri tidak perlu menekan database untuk mendapatkan data — melainkan mendapatkan hasil dari indeks itu sendiri. Contoh:kita telah mendefinisikan indeks komposit pada (pan_no, name, age)
, jadi sekarang pertimbangkan kueri berikut:
SELECT age FROM index_demo WHERE pan_no = 'HJKXS9086W' AND name = 'kousik'
Kolom yang disebutkan dalam SELECT
&WHERE
klausa adalah bagian dari indeks komposit. Jadi dalam hal ini, kita sebenarnya bisa mendapatkan nilai age
kolom dari indeks komposit itu sendiri. Mari kita lihat apa yang EXPLAIN
perintah ditampilkan untuk kueri ini:
EXPLAIN FORMAT=JSON SELECT age FROM index_demo WHERE pan_no = 'HJKXS9086W' AND name = '111kousik1';
Dalam respons di atas, perhatikan bahwa ada kunci — using_index
yang disetel ke true
yang menandakan bahwa indeks penutup telah digunakan untuk menjawab pertanyaan tersebut.
Saya tidak tahu berapa banyak indeks penutup yang dihargai di lingkungan produksi, tetapi tampaknya ini merupakan pengoptimalan yang baik jika kueri sesuai dengan tagihan.
Indeks Sebagian:
Kami sudah tahu bahwa Indeks mempercepat kueri kami dengan mengorbankan ruang. Semakin banyak indeks yang Anda miliki, semakin banyak kebutuhan penyimpanan. Kami telah membuat indeks bernama secondary_idx_1
pada kolom name
. Kolom name
dapat berisi nilai besar dengan panjang berapa pun. Juga dalam indeks, metadata pencari baris atau penunjuk baris memiliki ukurannya sendiri. Jadi secara keseluruhan, sebuah indeks dapat memiliki penyimpanan &beban memori yang tinggi.
Di MySQL, dimungkinkan untuk membuat indeks pada beberapa byte data pertama juga. Contoh:perintah berikut membuat indeks pada 4 byte pertama nama. Meskipun metode ini mengurangi overhead memori dengan jumlah tertentu, indeks tidak dapat menghilangkan banyak baris, karena dalam contoh ini 4 byte pertama mungkin umum di banyak nama. Biasanya pengindeksan awalan semacam ini didukung di CHAR
,VARCHAR
, BINARY
, VARBINARY
jenis kolom.
CREATE INDEX secondary_index_1 ON index_demo (name(4));
Apa yang terjadi di balik layar ketika kita mendefinisikan indeks?
Mari kita jalankan SHOW EXTENDED
perintah lagi:
SHOW EXTENDED INDEXES FROM index_demo;
Kami mendefinisikan secondary_index_1
di name
, tetapi MySQL telah membuat indeks komposit pada (name
, phone_no
) di mana phone_no
adalah kolom kunci utama. Kami membuat secondary_index_2
pada age
&MySQL membuat indeks komposit pada (age
, phone_no
). Kami membuat composite_index_2
aktif (pan_no
, name
, age
) &MySQL telah membuat indeks komposit pada (pan_no
, name
, age
, phone_no
). Indeks gabungan composite_index_1
sudah memiliki phone_no
sebagai bagian darinya.
Jadi indeks apa pun yang kami buat, MySQL di latar belakang membuat indeks komposit pendukung yang pada gilirannya menunjuk ke kunci utama. Ini berarti bahwa kunci utama adalah warga negara kelas satu di dunia pengindeksan MySQL. It also proves that all the indexes are backed by a copy of the primary index —but I am not sure whether a single copy of the primary index is shared or different copies are used for different indexes.
There are many other indices as well like Spatial index and Full Text Search index offered by MySQL. I have not yet experimented with those indices, so I’m not discussing them in this post.
General Indexing guidelines:
- Since indices consume extra memory, carefully decide how many &what type of index will suffice your need.
- With
DML
operations, indices are updated, so write operations are quite costly with indexes. The more indices you have, the greater the cost. Indexes are used to make read operations faster. So if you have a system that is write heavy but not read heavy, think hard about whether you need an index or not. - Cardinality is important — cardinality means the number of distinct values in a column. If you create an index in a column that has low cardinality, that’s not going to be beneficial since the index should reduce search space. Low cardinality does not significantly reduce search space.
Example:if you create an index on a boolean (int
1
or0
only ) type column, the index will be very skewed since cardinality is less (cardinality is 2 here). But if this boolean field can be combined with other columns to produce high cardinality, go for that index when necessary. - Indices might need some maintenance as well if old data still remains in the index. They need to be deleted otherwise memory will be hogged, so try to have a monitoring plan for your indices.
In the end, it’s extremely important to understand the different aspects of database indexing. It will help while doing low level system designing. Many real-life optimizations of our applications depend on knowledge of such intricate details. A carefully chosen index will surely help you boost up your application’s performance.
Please do clap &share with your friends &on social media if you like this article. :)
References:
- https://dev.mysql.com/doc/refman/5.7/en/innodb-index-types.html
- https://www.quora.com/What-is-difference-between-primary-index-and-secondary-index-exactly-And-whats-advantage-of-one-over-another
- https://dev.mysql.com/doc/refman/8.0/en/create-index.html
- https://www.oreilly.com/library/view/high-performance-mysql/0596003064/ch04.html
- http://www.unofficialmysqlguide.com/covering-indexes.html
- https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html
- https://dev.mysql.com/doc/refman/8.0/en/show-index.html
- https://dev.mysql.com/doc/refman/8.0/en/create-index.html