MariaDB
 sql >> Teknologi Basis Data >  >> RDS >> MariaDB

Panduan untuk Indeks MySQL

Saat pengoptimalan kueri MySQL disebutkan, indeks adalah salah satu hal pertama yang dibahas. Hari ini, kita akan mencoba melihat mengapa mereka begitu penting.

Apa itu Indeks?

Secara umum, indeks adalah daftar abjad catatan dengan referensi ke halaman di mana mereka disebutkan. Di MySQL, indeks adalah struktur data yang digunakan untuk menemukan baris dengan cepat. Indeks juga disebut kunci dan kunci tersebut sangat penting untuk kinerja yang baik - seiring bertambahnya data, kebutuhan untuk menggunakan indeks dengan benar mungkin menjadi semakin penting. Menggunakan indeks adalah salah satu cara paling ampuh untuk meningkatkan kinerja kueri - jika indeks digunakan dengan benar, kinerja kueri dapat meningkat puluhan atau bahkan ratusan kali.

Hari ini, kami akan mencoba menjelaskan keuntungan dan kerugian dasar menggunakan indeks di MySQL. Ingatlah bahwa indeks MySQL saja layak mendapatkan seluruh buku sehingga posting ini tidak akan mencakup semuanya, tetapi ini akan menjadi titik awal yang baik. Bagi mereka yang tertarik dengan cara kerja indeks pada tingkat yang lebih dalam, membaca buku Relational Database Index Design and the Optimizers oleh Tapio Lahdenmäki dan Michael Leach akan memberikan lebih banyak wawasan.

Manfaat Menggunakan Indeks

Ada beberapa manfaat utama menggunakan indeks di MySQL dan ini adalah sebagai berikut:

  • Indeks memungkinkan untuk menemukan baris yang cocok dengan klausa WHERE dengan cepat;
  • Indeks dapat membantu kueri menghindari pencarian melalui baris tertentu sehingga mengurangi jumlah data yang perlu diperiksa server - jika ada pilihan antara beberapa indeks, MySQL biasanya menggunakan indeks yang paling selektif, yaitu indeks yang menemukan jumlah baris terkecil;
  • Indeks mungkin digunakan untuk mengambil baris dari tabel lain dalam operasi GABUNG;
  • Indeks dapat digunakan untuk menemukan nilai minimum atau maksimum dari kolom tertentu yang menggunakan indeks;
  • Indeks dapat digunakan untuk mengurutkan atau mengelompokkan tabel jika operasi dilakukan pada awalan indeks paling kiri - demikian pula, awalan paling kiri dari indeks multi-kolom juga dapat digunakan oleh pengoptimal kueri untuk mencari baris;
  • Indeks juga dapat digunakan untuk menyimpan I/O disk - saat indeks penutup sedang digunakan, kueri dapat mengembalikan nilai langsung dari struktur indeks yang menyimpan I/O disk.

Demikian pula, ada beberapa jenis indeks:

  • INDEX adalah jenis indeks yang nilainya tidak harus unik. Jenis indeks ini menerima nilai NULL;
  • UNIQUE INDEX sering digunakan untuk menghapus baris duplikat dari tabel - jenis indeks ini memungkinkan pengembang untuk menerapkan keunikan nilai baris;
  • FULLTEXT INDEX adalah indeks yang diterapkan pada bidang yang memanfaatkan kemampuan penelusuran teks lengkap. Jenis indeks ini menemukan kata kunci dalam teks alih-alih langsung membandingkan nilai dengan nilai dalam indeks;
  • DESCENDING INDEX adalah indeks yang menyimpan baris dalam urutan menurun - pengoptimal kueri akan memilih jenis indeks ini saat urutan menurun diminta oleh kueri. Jenis indeks ini diperkenalkan di MySQL 8.0;
  • PRIMARY KEY juga merupakan indeks. Singkatnya, PRIMARY KEY adalah kolom atau kumpulan kolom yang mengidentifikasi setiap baris dalam tabel - sering digunakan bersama dengan bidang yang memiliki atribut AUTO_INCREMENT. Jenis indeks ini tidak menerima nilai NULL dan setelah disetel, nilai dalam PRIMARY KEY tidak dapat diubah.

Sekarang, kita akan mencoba membahas keuntungan dan kerugian menggunakan indeks di MySQL. Kita akan mulai dengan hal terbalik yang mungkin paling sering dibahas - mempercepat kueri yang cocok dengan klausa WHERE.

Mempercepat Kueri yang Mencocokkan Klausa WHERE

Indeks sering digunakan untuk mempercepat kueri penelusuran yang cocok dengan klausa WHERE. Alasan mengapa indeks membuat operasi pencarian lebih cepat cukup sederhana - kueri yang menggunakan indeks menghindari pemindaian tabel penuh.

Untuk mempercepat kueri yang cocok dengan klausa WHERE, Anda dapat menggunakan pernyataan EXPLAIN di MySQL. Pernyataan EXPLAIN SELECT seharusnya memberi Anda beberapa wawasan tentang bagaimana pengoptimal kueri MySQL mengeksekusi kueri - itu juga dapat menunjukkan kepada Anda apakah kueri tersebut menggunakan indeks atau tidak dan indeks apa yang digunakannya. Simak penjelasan query berikut ini:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

Kueri di atas tidak menggunakan indeks. Namun, jika kita menambahkan indeks pada “field_1”, indeks akan berhasil digunakan:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

Kolom possible_keys menjelaskan kemungkinan indeks yang dapat dipilih MySQL, kolom kunci menjelaskan indeks yang sebenarnya dipilih dan kolom key_len menjelaskan panjang kunci yang dipilih.

Dalam hal ini, MySQL akan melakukan pencarian nilai dalam indeks dan mengembalikan setiap baris yang berisi nilai yang ditentukan - sebagai hasilnya, kueri akan lebih cepat. Meskipun indeks membantu kueri tertentu menjadi lebih cepat, ada beberapa hal yang perlu diingat jika Anda ingin indeks membantu kueri Anda:

  • Isolasi kolom Anda - MySQL tidak dapat menggunakan indeks jika kolom tempat indeks digunakan tidak diisolasi. Misalnya, kueri seperti ini tidak akan menggunakan indeks:
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

Untuk mengatasi ini, biarkan kolom setelah klausa WHERE saja - sederhanakan kueri Anda sebanyak mungkin dan isolasi kolom;

  • Hindari menggunakan kueri LIKE dengan karakter pengganti sebelumnya - dalam hal ini, MySQL tidak akan menggunakan indeks karena karakter pengganti sebelumnya berarti bahwa bisa ada apa saja sebelum teks. Jika Anda harus menggunakan kueri LIKE dengan karakter pengganti dan ingin kueri menggunakan indeks, pastikan karakter pengganti berada di akhir pernyataan penelusuran.

Tentu saja, mempercepat kueri yang cocok dengan klausa WHERE juga dapat dilakukan dengan cara lain (misalnya, mempartisi), tetapi demi kesederhanaan, kami tidak akan membahasnya lebih jauh dalam postingan ini.

Namun, yang mungkin menarik bagi kami adalah jenis jenis indeks yang berbeda, jadi kami akan memeriksanya sekarang.

Menyingkirkan Nilai Duplikat dalam Kolom - Indeks UNIK

Tujuan indeks UNIK di MySQL adalah untuk menegakkan keunikan nilai dalam kolom. Untuk menggunakan indeks UNIK, jalankan kueri CREATE UNIQUE INDEX:

CREATE UNIQUE INDEX demo_index ON demo_table(demo_column);

You can also create a unique index when you create a table:

CREATE TABLE demo_table (
`demo_column` VARCHAR(100) NOT NULL,
UNIQUE KEY(demo_column)
);

Hanya itu yang diperlukan untuk menambahkan indeks unik ke tabel. Sekarang, ketika Anda mencoba menambahkan nilai duplikat ke tabel, MySQL akan kembali dengan kesalahan berikut:

#1062 - Duplicate entry ‘Demo’ for key ‘demo_column’

Indeks FULLTEXT

Indeks FULLTEXT adalah indeks yang diterapkan ke kolom yang menggunakan kemampuan penelusuran teks lengkap. Jenis indeks ini memiliki banyak kemampuan unik termasuk stopwords dan mode pencarian.

Daftar stopword InnoDB memiliki 36 kata sedangkan daftar stopword MyISAM memiliki 143. Di InnoDB, stopword diturunkan dari tabel yang ditetapkan dalam variabel innodb_ft_user_stopword_table, jika tidak, jika variabel ini tidak disetel, maka akan diturunkan dari variabel innodb_ft_server_stopword_table. Jika tidak satu pun dari kedua variabel tersebut disetel, InnoDB menggunakan daftar bawaan. Untuk melihat daftar stopword default InnoDB, kueri tabel INNODB_FT_DEFAULT_STOPWORD.

Dalam MyISAM, stopword berasal dari file storage/myisam/ft_static.c. Variabel ft_stopword_file memungkinkan daftar stopword default diubah. Stopwords akan dinonaktifkan jika variabel ini disetel ke string kosong, tetapi perlu diingat bahwa jika variabel ini mendefinisikan file, file yang ditentukan tidak diuraikan untuk komentar - MyISAM akan memperlakukan semua kata yang ditemukan dalam file sebagai stopwords.

Indeks FULLTEXT juga terkenal dengan mode pencariannya yang unik:

  • Jika permintaan pencarian FULLTEXT tanpa pengubah dijalankan, mode bahasa alami akan diaktifkan. Mode bahasa alami juga dapat diaktifkan dengan menggunakan pengubah IN NATURAL LANGUAGE MODE;
  • Pengubah WITH QUERY EXPANSION mengaktifkan mode penelusuran dengan perluasan kueri. Mode pencarian seperti itu bekerja dengan melakukan pencarian dua kali dan ketika pencarian dijalankan untuk kedua kalinya, kumpulan hasil akan menyertakan beberapa dokumen yang paling relevan dari pencarian pertama. Secara umum, pengubah ini berguna ketika pengguna memiliki beberapa pengetahuan tersirat (misalnya, pengguna mungkin mencari “database” dan berharap untuk melihat “InnoDB” dan “MyISAM” di kumpulan hasil);
  • Pengubah IN BOOLEAN MODE memungkinkan pencarian dengan operator boolean. Misalnya, operator +, - atau * masing-masing akan menyelesaikan tugas yang berbeda - operator + akan mendefinisikan bahwa nilai harus ada dalam satu baris, operator - akan mendefinisikan bahwa nilai tidak boleh ada dan operator * akan bertindak sebagai karakter pengganti.

Kueri yang menggunakan indeks FULLTEXT terlihat seperti ini:

SELECT * FROM demo_table WHERE MATCH(demo_field) AGAINST(‘value’ IN NATURAL LANGUAGE MODE);

Perlu diingat bahwa indeks FULLTEXT umumnya berguna untuk operasi MATCH() AGAINST() - bukan untuk operasi WHERE yang berarti bahwa jika klausa WHERE akan digunakan, kegunaan menggunakan jenis indeks yang berbeda tidak akan dihilangkan.

Perlu disebutkan juga bahwa indeks FULLTEXT memiliki panjang karakter minimum. Di InnoDB, pencarian FULLTEXT hanya dapat dilakukan bila permintaan pencarian terdiri dari minimal tiga karakter - batas ini ditingkatkan menjadi empat karakter di mesin penyimpanan MyISAM.

Indeks TURUN

Indeks DESCENDING adalah indeks di mana InnoDB menyimpan entri dalam urutan menurun - pengoptimal kueri akan menggunakan indeks seperti itu ketika urutan menurun diminta oleh kueri. Indeks semacam itu dapat ditambahkan ke kolom dengan menjalankan kueri seperti di bawah ini:

CREATE INDEX descending_index ON demo_table(column_name DESC);

Indeks menaik juga dapat ditambahkan ke kolom - cukup ganti DESC dengan ASC.

KUNCI UTAMA

KUNCI UTAMA berfungsi sebagai pengidentifikasi unik untuk setiap baris dalam sebuah tabel. Kolom dengan KUNCI UTAMA harus berisi nilai unik - nilai NULL juga tidak boleh digunakan. Jika nilai duplikat ditambahkan ke kolom yang memiliki KUNCI UTAMA, MySQL akan merespons dengan kesalahan #1062:

#1062 - Duplicate entry ‘Demo’ for key ‘PRIMARY’

Jika nilai NULL ditambahkan ke kolom, MySQL akan merespons dengan kesalahan #1048:

#1048 - Column ‘id’ cannot be null

Indeks utama terkadang juga disebut indeks berkerumun (kita akan membahasnya nanti).

Anda juga dapat membuat indeks pada beberapa kolom sekaligus - indeks tersebut disebut indeks multikolom.

Indeks Multikolom

Indeks pada beberapa kolom sering disalahpahami - terkadang pengembang dan DBA mengindeks semua kolom secara terpisah atau mengindeksnya dalam urutan yang salah. Untuk membuat kueri menggunakan indeks multikolom seefektif mungkin, ingatlah bahwa urutan kolom dalam indeks yang menggunakan lebih dari satu kolom adalah salah satu penyebab paling umum kebingungan di ruang ini - karena tidak ada "jalan ini atau jalan raya". ” solusi urutan indeks, Anda harus ingat bahwa urutan indeks multikolom yang benar bergantung pada kueri yang menggunakan indeks. Meskipun ini mungkin tampak cukup jelas, ingatlah bahwa urutan kolom sangat penting ketika berhadapan dengan indeks multicolumn - pilih urutan kolom sedemikian rupa sehingga seselektif mungkin untuk kueri yang paling sering dijalankan.

Untuk mengukur selektivitas untuk kolom tertentu, dapatkan rasio jumlah nilai indeks yang berbeda dengan jumlah total baris dalam tabel - kolom yang memiliki selektivitas lebih tinggi harus menjadi yang pertama .

Terkadang Anda juga perlu mengindeks kolom karakter yang sangat panjang, dan dalam hal ini, Anda sering dapat menghemat waktu dan sumber daya dengan mengindeks beberapa karakter pertama - awalan - alih-alih seluruh nilai.

Indeks Awalan

Indeks awalan dapat berguna bila kolom berisi nilai string yang sangat panjang, yang berarti bahwa menambahkan indeks pada seluruh kolom akan menghabiskan banyak ruang disk. MySQL membantu untuk mengatasi masalah ini dengan memungkinkan Anda untuk hanya mengindeks awalan dari nilai yang pada gilirannya membuat ukuran indeks lebih kecil. Lihat:

CREATE TABLE `demo_table` (
`demo_column` VARCHAR(100) NOT NULL,
INDEX(demo_column(10))
);

Kueri di atas akan membuat indeks awalan pada kolom demo yang hanya mengindeks 10 karakter pertama dari nilai tersebut. Anda juga dapat menambahkan indeks awalan ke tabel yang ada:

CREATE INDEX index_name ON table_name(column_name(length));

Jadi, misalnya, jika Anda ingin mengindeks 5 karakter pertama dari kolom_demo pada tabel_demo, Anda dapat menjalankan kueri berikut:

CREATE INDEX demo_index ON demo_table(demo_column(5));

Anda harus memilih awalan yang cukup panjang untuk memberikan selektivitas, tetapi juga cukup pendek untuk memberi ruang. Ini mungkin lebih mudah diucapkan daripada dilakukan - Anda perlu bereksperimen dan menemukan solusi yang sesuai untuk Anda.

Meliputi Indeks

Indeks penutup "mencakup" semua bidang yang diperlukan untuk menjalankan kueri. Dengan kata lain, ketika semua bidang dalam kueri dicakup oleh indeks, indeks penutup sedang digunakan. Misalnya untuk kueri seperti ini:

SELECT id, title FROM demo_table WHERE id = 1;

Indeks penutup mungkin terlihat seperti ini:

INDEX index_name(id, title);

Jika Anda ingin memastikan bahwa kueri menggunakan indeks penutup, keluarkan pernyataan JELASKAN padanya, lalu lihat kolom Ekstra. Misalnya, jika tabel Anda memiliki indeks multikolom pada id dan judul dan kueri yang hanya mengakses dua kolom ini dijalankan, MySQL akan menggunakan indeks:

mysql> EXPLAIN SELECT id, title FROM demo_table \G;

*************************** 1. row ***************************

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Perlu diingat bahwa indeks penutup harus menyimpan nilai dari kolom yang dicakupnya. Itu berarti MySQL hanya dapat menggunakan indeks B-Tree untuk menutupi kueri karena jenis indeks lain tidak menyimpan nilai ini.

Berkelompok, Indeks Sekunder, dan Kardinalitas Indeks

Saat indeks dibahas, Anda mungkin juga mendengar istilah berkerumun, indeks sekunder, dan kardinalitas indeks. Sederhananya, indeks berkerumun adalah pendekatan untuk penyimpanan data dan semua indeks selain indeks berkerumun adalah indeks sekunder. Kardinalitas indeks di sisi lain adalah jumlah nilai unik dalam indeks.

Indeks berkerumun mempercepat kueri karena nilai yang dekat juga disimpan berdekatan satu sama lain di disk, tetapi itu juga alasan mengapa Anda hanya dapat memiliki satu indeks berkerumun dalam sebuah tabel.

Indeks sekunder adalah indeks apa pun yang bukan indeks utama. Indeks semacam itu mungkin memiliki duplikat.

Kelemahan Menggunakan Indeks

Penggunaan indeks tentu memiliki kelebihan, tetapi kita tidak boleh lupa bahwa indeks juga dapat menjadi salah satu penyebab utama masalah di MySQL. Beberapa kelemahan menggunakan indeks adalah sebagai berikut:

  • Indeks dapat menurunkan kinerja kueri tertentu - meskipun indeks cenderung mempercepat kinerja kueri SELECT, indeks dapat memperlambat kinerja kueri INSERT, UPDATE, dan DELETE karena saat data diperbarui indeks juga perlu diperbarui bersama dengannya:operasi apa pun yang melibatkan manipulasi indeks akan lebih lambat dari biasanya;
  • Indeks menghabiskan ruang disk - indeks menempati ruangnya sendiri, jadi data yang diindeks juga akan menghabiskan lebih banyak ruang disk;
  • Indeks yang berlebihan dan duplikat dapat menjadi masalah - MySQL memungkinkan Anda untuk membuat indeks duplikat pada kolom dan tidak "melindungi Anda" dari melakukan kesalahan seperti itu. Lihat contoh ini: 
    CREATE TABLE `demo_table` (
    
    `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    
    `column_2` VARCHAR(10) NOT NULL,
    
    `column_3` VARCHAR(10) NOT NULL,
    
    INDEX(id),
    
    UNIQUE(id)
    
    );

Pengguna yang tidak berpengalaman mungkin berpikir bahwa kueri ini membuat kolom id bertambah secara otomatis, lalu menambahkan indeks pada kolom dan membuat kolom tidak menerima nilai duplikat. Namun, bukan ini yang terjadi di sini. Dalam hal ini, kolom yang sama memiliki tiga indeks di atasnya:INDEX biasa, dan karena MySQL mengimplementasikan kendala PRIMARY KEY dan UNIQUE dengan indeks, itu menambahkan dua indeks lagi pada kolom yang sama!

Kesimpulan

Untuk menyimpulkan, indeks di MySQL memiliki tempatnya sendiri - indeks dapat digunakan dalam banyak skenario, tetapi masing-masing skenario penggunaan tersebut memiliki kelemahannya sendiri yang harus dipertimbangkan untuk mendapatkan hasil maksimal dari indeks yang sedang digunakan.

Untuk menggunakan indeks dengan baik, buat profil kueri Anda, lihat opsi apa yang Anda miliki ketika datang ke indeks, ketahui manfaat dan kerugiannya, putuskan indeks apa yang Anda butuhkan berdasarkan kebutuhan Anda dan setelah Anda mengindeks kolom, pastikan indeks Anda sebenarnya digunakan oleh MySQL. Jika Anda telah mengindeks skema dengan benar, kinerja kueri Anda akan meningkat, tetapi jika waktu respons tidak memuaskan Anda, lihat apakah indeks yang lebih baik dapat dibuat untuk meningkatkannya.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menggunakan Plugin Log Audit Percona untuk Keamanan Basis Data

  2. Daftar Lengkap Koleksi yang Didukung oleh MariaDB

  3. Bagaimana YEAR() Bekerja di MariaDB

  4. 4 Cara untuk Memisahkan Jam, Menit, dan Detik dari Nilai Waktu di MariaDB

  5. MariaDB LOCALTIME() Dijelaskan