Bagaimana cara menambahkan indeks ke tabel MySQL?

407

Saya punya tabel MySQL yang sangat besar dengan sekitar 150.000 baris data. Saat ini, ketika saya mencoba dan menjalankan

SELECT * FROM table WHERE id = '1';

kode berfungsi dengan baik karena bidang ID adalah indeks utama. Namun, untuk pengembangan terbaru dalam proyek ini, saya harus mencari basis data dengan bidang lain. Sebagai contoh:

SELECT * FROM table WHERE product_id = '1';

Bidang ini sebelumnya tidak diindeks; Namun, saya telah menambahkan satu, jadi mysql sekarang mengindeks bidang, tetapi ketika saya mencoba menjalankan kueri di atas, ia berjalan sangat lambat. Kueri EXPLAIN mengungkapkan bahwa tidak ada indeks untuk bidang product_id ketika saya sudah menambahkannya, dan sebagai hasilnya kueri membutuhkan waktu mulai dari 20 menit hingga 30 menit untuk mengembalikan satu baris.

Hasil lengkap EXPLAIN saya adalah:

| id | select_type | table | type | possible_keys| key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+
|  1 | SIMPLE      | table | ALL  | NULL         | NULL | NULL    | NULL |157211 | Using where |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+

Mungkin bermanfaat untuk dicatat bahwa saya baru saja melihatnya, dan bidang ID disimpan sebagai INT sedangkan bidang PRODUCT_ID disimpan sebagai VARCHAR. Mungkinkah ini sumber masalahnya?

Michael
sumber
1
Bisakah Anda memposting EXPLAINhasil lengkap ? Apakah Anda yakin tidak ada indeks? Atau ada indeks di sana, tetapi MySQL memilih untuk tidak menggunakannya?
VoteyDisciple
169
Meja besar akan memiliki 150.000.000 catatan. Tabel yang sangat besar memiliki 15.000.000.000 catatan. Tabel ukuran rata-rata memiliki 150.000. Untuk referensi di masa mendatang.
usumoio
4
Sadarilah bahwa 'ATAU' dapat membuat MySql tidak menggunakan indeks. Saya punya pertanyaan dengan 3 OR. Setiap membuat indeks, dan berlari dalam 15 ms, Semua bersama-sama mengambil antara 25 detik dan batas waktu. Jadi saya membuat 3 pertanyaan dan menyatukannya bersama-sama, butuh 15ms pada 500.000 baris.
Leif Neland
Pertimbangkan tipe data yang Anda simpan. Kinerja dapat berubah berdasarkan pada tipe data yang Anda bandingkan. Seperti yang Anda katakan PRODUCT_ID adalah tipe data VARCHAR, coba ubah ke INT dan indeks kolom.
gilbertdim

Jawaban:

606
ALTER TABLE `table` ADD INDEX `product_id_index` (`product_id`)

Jangan pernah dibandingkan integerdengan stringsdi MySQL. Jika idadalah int, menghapus tanda kutip.

zerkms
sumber
Saya sudah menambahkan indeks menggunakan SQL yang tepat tetapi tampaknya belum "diterapkan" ke data dan permintaan EXPLAIN menunjukkan bahwa tidak ada indeks untuk bidang tersebut.
Michael
1
Peduli untuk memeriksa indeks dengan SHOW CREATE TABLE, atau sudahkah Anda melakukannya?
Wrikken
33
Gunakan SHOW INDEXES FROM YOURTABLE dev.mysql.com/doc/refman/5.0/id/show-index.html untuk memeriksa apakah indeks telah ditambahkan
Timo Huovinen
6
Hari ini saya memiliki masalah yang persis dijelaskan oleh @Michael, dan solusinya adalah "Jangan pernah membandingkan integer dengan string di mysql." Terima kasih.
user12345
@Wrikken Saya menambahkan indeks saya dan menggunakan perintah Anda TAMPILKAN INDEKS DARI ANDA. Itu muncul tetapi saya tidak berpikir itu digunakan saat saya meminta meja saya. Apakah saya harus mengubah kueri pemilihan saat menggunakan indeks?
Ced
148
ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);
pabloferraz
sumber
97
Dalam MySQL, jika Anda menggunakan ALTER TABLE tbl ADD INDEX (col)bukan ALTER TABLE tbl ADD INDEX col (col), kemudian menggunakan ALTER TABLE tbl ADD INDEX (col)lebih dari sekali akan terus menambahkan indeks bernama col_2, col_3... setiap kali. Sedangkan menggunakan ALTER TABLE tbl ADD INDEX col (col)waktu ke - 2, akan memberi ERROR 1061 (42000): Duplicate key name 'col'.
Abhishek Oza
82

Anda dapat menggunakan sintaks ini untuk menambahkan indeks dan mengontrol jenis indeks (HASH atau BTREE).

create index your_index_name on your_table_name(your_column_name) using HASH;
or
create index your_index_name on your_table_name(your_column_name) using BTREE;

Anda dapat mempelajari tentang perbedaan antara indeks BTREE dan HASH di sini: http://dev.mysql.com/doc/refman/5.5/id/index-btree-hash.html

Hieu Vo
sumber
1
Hash dikonversi ke btree ketika saya melihat menggunakan indeks acara.
RN Kushwaha
1
Apa yang akan menjadi default dari Hash dan BTree, jika saya tidak menentukannya?
Bhavuk Mathur
2
@RNKushwaha karena InnoDB dan MyIsam tidak mendukung HASH, AFAIK, hanya mesin memori dan penyimpanan NDB yang mendukungnya
Hieu Vo
60

Perlu dicatat bahwa beberapa indeks bidang dapat secara drastis meningkatkan kinerja kueri Anda. Jadi, dalam contoh di atas kita menganggap ProductID adalah satu-satunya bidang untuk pencarian tetapi permintaan untuk mengatakan ProductID = 1 DAN Kategori = 7 maka indeks beberapa kolom membantu. Ini dicapai dengan yang berikut:

ALTER TABLE `table` ADD INDEX `index_name` (`col1`,`col2`)

Selain itu indeks harus cocok dengan urutan bidang kueri. Dalam contoh saya yang diperluas indeks harus (ProductID, Kategori) bukan sebaliknya.

Antony
sumber
1
Bagus, penamaan indeks secara eksplisit memungkinkan untuk pembalikan mudah.
Sam Berry
Bisakah Anda mengutip sumber dari the index should match the order of the query fields?
Bishwas Mishra
58

Indeks dari dua jenis dapat ditambahkan: ketika Anda mendefinisikan kunci utama, MySQL akan menjadikannya sebagai indeks secara default.

Penjelasan

Kunci utama sebagai indeks

Pertimbangkan Anda memiliki tbl_studenttabel dan Anda ingin student_idsebagai kunci utama:

ALTER TABLE `tbl_student` ADD PRIMARY KEY (`student_id`)

Pernyataan di atas menambahkan kunci utama, yang berarti bahwa nilai yang diindeks harus unik dan tidak boleh NULL.

Tentukan nama indeks

ALTER TABLE `tbl_student` ADD INDEX student_index (`student_id`)

Pernyataan di atas akan membuat indeks biasa dengan student_indexnama.

Buat indeks unik

ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)

Di sini, student_unique_indexadalah nama indeks yang ditetapkan untuk student_id dan membuat indeks yang nilainya harus unik (di sini nol dapat diterima).

Opsi teks lengkap

ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)

Pernyataan di atas akan membuat nama indeks Fulltext dengan student_fulltext_index, di mana Anda memerlukan MyISAM Mysql Engine.

Bagaimana cara menghapus indeks?

DROP INDEX `student_index` ON `tbl_student`

Bagaimana cara memeriksa indeks yang tersedia?

SHOW INDEX FROM `tbl_student`
Jazzzzzz
sumber
17

Anda mengatakan Anda memiliki indeks, yang menjelaskan mengatakan sebaliknya. Namun, jika Anda benar-benar melakukannya, ini adalah cara untuk melanjutkan:

Jika Anda memiliki indeks pada kolom, dan MySQL memutuskan untuk tidak menggunakannya, itu mungkin karena:

  1. Ada indeks lain dalam kueri yang dianggap lebih tepat untuk digunakan oleh MySQL, dan hanya dapat digunakan satu. Solusinya biasanya indeks yang mencakup beberapa kolom jika metode pengambilan normal adalah dengan nilai lebih dari satu kolom.
  2. MySQL memutuskan ada banyak baris yang cocok, dan berpikir tablescan mungkin lebih cepat. Jika bukan itu masalahnya, terkadang ANALYZE TABLEbantuan.
  3. Dalam pertanyaan yang lebih kompleks, ia memutuskan untuk tidak menggunakannya berdasarkan pemikiran voodoo yang sangat cerdas dalam rencana permintaan yang karena alasan tertentu tidak cocok dengan kebutuhan Anda saat ini.

Dalam kasus (2) atau (3), Anda dapat membujuk MySQL untuk menggunakan indeks menurut indeks petunjuk sytax , tetapi jika Anda melakukannya, pastikan menjalankan beberapa tes untuk menentukan apakah itu benar-benar meningkatkan kinerja untuk menggunakan indeks saat Anda mengisinya .

Terkutuk
sumber