ฉันจะเพิ่มดัชนีลงในตาราง MySQL ได้อย่างไร


407

ฉันมีตาราง MySQL ที่มีขนาดใหญ่มากพร้อมข้อมูลประมาณ 150,000 แถว ขณะนี้เมื่อฉันลองและเรียกใช้

SELECT * FROM table WHERE id = '1';

รหัสทำงานได้ดีเนื่องจากฟิลด์ ID เป็นดัชนีหลัก อย่างไรก็ตามสำหรับการพัฒนาล่าสุดของโครงการฉันต้องค้นหาฐานข้อมูลตามฟิลด์อื่น ตัวอย่างเช่น:

SELECT * FROM table WHERE product_id = '1';

ฟิลด์นี้ไม่ได้จัดทำดัชนีไว้ก่อนหน้านี้ อย่างไรก็ตามฉันได้เพิ่มเข้าไปแล้วดังนั้นตอนนี้ mysql จะสร้างดัชนีฟิลด์ แต่เมื่อฉันพยายามเรียกใช้แบบสอบถามข้างต้นมันจะทำงานช้ามาก คำค้นหาอธิบายเปิดเผยว่าไม่มีดัชนีสำหรับฟิลด์ product_id เมื่อฉันได้เพิ่มไปแล้วและด้วยเหตุนี้แบบสอบถามจึงใช้เวลาตั้งแต่ 20 นาทีถึง 30 นาทีในการส่งคืนแถวเดียว

ผลการสำรวจอย่างสมบูรณ์ของฉันคือ:

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

อาจเป็นประโยชน์ที่จะทราบว่าฉันเพิ่งดูและฟิลด์ ID ถูกเก็บเป็น INT ขณะที่ฟิลด์ PRODUCT_ID ถูกเก็บเป็น VARCHAR นี่อาจเป็นสาเหตุของปัญหาหรือไม่


1
คุณสามารถโพสต์EXPLAINผลเต็มรูปแบบ? คุณแน่ใจหรือว่าไม่มีดัชนี? หรือมีดัชนีอยู่ แต่ MySQL เลือกที่จะไม่ใช้มัน
VoteyDisciple

169
ตารางขนาดใหญ่จะมีระเบียน 150,000,000 รายการ ตารางที่มีขนาดใหญ่มากมีจำนวน 15,000,000,000 รายการ ตารางขนาดเฉลี่ยมี 150,000 สำหรับการอ้างอิงในอนาคต.
usumoio

4
ระวังว่า 'หรือ' สามารถทำให้ MySql ไม่ใช้ดัชนี ฉันมีแบบสอบถามด้วย 3 หรือ แต่ละคนทำดัชนีและวิ่งใน 15 มิลลิวินาทีทั้งหมดรวมกันใช้เวลาระหว่าง 25 วินาทีและหมดเวลา ดังนั้นฉันจึงทำแบบสอบถาม 3 ข้อและยูเนี่ยนรวมเข้าด้วยกันมันใช้เวลา 15ms ใน 500,000 แถว
Leif Neland

พิจารณาประเภทข้อมูลที่คุณจัดเก็บ ประสิทธิภาพอาจเปลี่ยนแปลงตามประเภทข้อมูลที่คุณกำลังเปรียบเทียบ ดังที่คุณกล่าวว่า PRODUCT_ID เป็นประเภทข้อมูล VARCHAR ลองเปลี่ยนเป็น INT และสร้างดัชนีคอลัมน์
gilbertdim

คำตอบ:


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

อย่าเปรียบเทียบintegerกับstringsใน MySQL หากidเป็นintเช่นนั้นให้ลบเครื่องหมายคำพูด


ฉันได้เพิ่มดัชนีโดยใช้ SQL นั้น แต่ดูเหมือนว่าไม่ได้ "นำไปใช้" กับข้อมูลและแบบสอบถามอธิบายแสดงให้เห็นว่าไม่มีดัชนีสำหรับฟิลด์
Michael

1
สนใจที่จะตรวจสอบดัชนีด้วย SHOW CREATE TABLE หรือคุณเคยทำมาแล้ว?
Wrikken

33
ใช้SHOW INDEXES FROM YOURTABLE dev.mysql.com/doc/refman/5.0/en/show-index.htmlเพื่อตรวจสอบว่ามีการเพิ่มดัชนีหรือไม่
Timo Huovinen

6
วันนี้ฉันมีปัญหาที่แน่นอน @Michael อธิบายและวิธีแก้ไขคือ "อย่าเปรียบเทียบจำนวนเต็มกับสตริงใน mysql" ขอบคุณ.
user12345

@Wrikken ฉันเพิ่มดัชนีของฉันและใช้คำสั่งของคุณ SHOW INDEXES จาก YOURTABLE มันปรากฏขึ้น แต่ฉันไม่คิดว่ามันจะใช้ในขณะที่ฉันค้นหาตารางของฉัน ฉันต้องเปลี่ยนแบบสอบถามแบบใช้เลือกข้อมูลเมื่อใช้ดัชนีหรือไม่
Ced

148
ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);

97
ใน MySQL ถ้าคุณใช้ALTER TABLE tbl ADD INDEX (col)แทนALTER TABLE tbl ADD INDEX col (col)แล้วใช้ALTER TABLE tbl ADD INDEX (col)มากกว่าหนึ่งครั้งจะเก็บเพิ่มดัชนีชื่อcol_2, col_3... ในแต่ละครั้ง ในขณะที่การใช้ALTER TABLE tbl ADD INDEX col (col)ครั้งที่ 2 ERROR 1061 (42000): Duplicate key name 'col'จะให้
Abhishek Oza

82

คุณสามารถใช้ไวยากรณ์นี้เพื่อเพิ่มดัชนีและควบคุมชนิดของดัชนี (HASH หรือ 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;

คุณสามารถเรียนรู้เกี่ยวกับความแตกต่างระหว่างดัชนี BTREE และ HASH ได้ที่นี่: http://dev.mysql.com/doc/refman/5.5/en/index-btree-hash.html


1
แฮชแปลงเป็น btree เมื่อฉันเห็นการใช้ดัชนีการแสดง
RN Kushwaha

1
อะไรจะเป็นค่าเริ่มต้นจาก Hash และ BTree หากฉันไม่ได้ระบุใด ๆ
Bhavuk Mathur

2
@RNKushwaha เพราะ InnoDB และ MyIsam ไม่รองรับ HASH, AFAIK เฉพาะเอ็นจิ้นหน่วยความจำและ NDB เท่านั้นที่สนับสนุน
Hieu Vo

60

เป็นที่น่าสังเกตว่าดัชนีฟิลด์หลายรายการสามารถปรับปรุงประสิทธิภาพการสืบค้นของคุณได้อย่างมาก ดังนั้นในตัวอย่างข้างต้นเราถือว่า ProductID เป็นเขตข้อมูลเดียวที่จะค้นหา แต่เป็นข้อความค้นหาที่จะพูดว่า ProductID = 1 AND Category = 7 ดังนั้นดัชนีหลายคอลัมน์จะช่วยได้ นี่คือความสำเร็จต่อไปนี้:

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

นอกจากนี้ดัชนีควรตรงกับลำดับของเขตข้อมูลแบบสอบถาม ในตัวอย่างเพิ่มเติมของฉันดัชนีควรเป็น (ProductID, Category) ไม่ใช่วิธีอื่น


1
ดีตั้งชื่อดัชนีอย่างชัดเจนช่วยให้สามารถกลับรายการได้ง่าย
Sam Berry

คุณสามารถอ้างอิงแหล่งที่มาของthe index should match the order of the query fields?
Bishwas Mishra

58

ดัชนีของสองประเภทสามารถเพิ่ม: เมื่อคุณกำหนดคีย์หลัก, MySQL จะใช้เป็นดัชนีตามค่าเริ่มต้น

คำอธิบาย

คีย์หลักเป็นดัชนี

พิจารณาว่าคุณมีtbl_studentตารางและคุณต้องการstudent_idเป็นคีย์หลัก:

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

ข้อความข้างต้นเพิ่มคีย์หลักซึ่งหมายความว่าค่าดัชนีจะต้องไม่ซ้ำกันและไม่สามารถเป็น NULL

ระบุชื่อดัชนี

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

ข้อความข้างต้นจะสร้างดัชนีสามัญด้วย student_indexชื่อ

สร้างดัชนีที่ไม่ซ้ำกัน

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

ที่นี่ student_unique_indexคือชื่อดัชนีที่กำหนดให้กับ student_id และสร้างดัชนีซึ่งค่าจะต้องไม่ซ้ำกัน (ที่นี่สามารถยอมรับได้ null)

ตัวเลือก Fulltext

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

ข้อความข้างต้นจะสร้างชื่อดัชนีแบบเต็มด้วย student_fulltext_indexซึ่งคุณต้องการ MyISAM Mysql Engine

จะลบดัชนีได้อย่างไร

DROP INDEX `student_index` ON `tbl_student`

วิธีตรวจสอบดัชนีที่มีอยู่

SHOW INDEX FROM `tbl_student`

17

คุณบอกว่าคุณมีดัชนีอธิบายว่าอย่างอื่น อย่างไรก็ตามถ้าคุณทำจริง ๆ นี่คือวิธีดำเนินการต่อ:

หากคุณมีดัชนีในคอลัมน์และ MySQL ตัดสินใจที่จะไม่ใช้มันอาจเป็นเพราะ:

  1. มีอีกดัชนีหนึ่งในแบบสอบถาม MySQL เห็นว่าเหมาะสมกว่าที่จะใช้และสามารถใช้ได้เพียงอันเดียว การแก้ปัญหามักจะเป็นดัชนีที่ครอบคลุมหลายคอลัมน์หากวิธีการสืบค้นแบบปกติของพวกเขานั้นมีค่ามากกว่าหนึ่งคอลัมน์
  2. MySQL ตัดสินใจว่ามีหลายแถวที่ตรงกันและคิดว่า tablescan น่าจะเร็วกว่า หากไม่เป็นเช่นนั้นบางครั้งก็ANALYZE TABLEช่วยได้
  3. ในการค้นหาที่ซับซ้อนมากขึ้นมันตัดสินใจที่จะไม่ใช้มันโดยพิจารณาจากข้อมูลที่คิดอย่างชาญฉลาดอย่างมากในแผนการค้นหาซึ่งด้วยเหตุผลบางประการเพียงไม่เหมาะกับความต้องการในปัจจุบันของคุณ

ในกรณีของ (2) หรือ (3) คุณสามารถเกลี้ยกล่อม MySQL ในการใช้ดัชนีโดยใช้ดัชนีคำใบ้ไวยากรณ์แต่ถ้าคุณทำให้แน่ใจว่าใช้การทดสอบบางอย่างเพื่อตรวจสอบว่าจะปรับปรุงประสิทธิภาพการใช้ดัชนีตามที่คุณแนะนำ .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.