ดัชนี MySQL ทำงานอย่างไร


402

ฉันสนใจจริง ๆ ว่าดัชนีของ MySQL ทำงานอย่างไรโดยเฉพาะพวกเขาจะคืนข้อมูลที่ร้องขอโดยไม่ต้องสแกนทั้งตารางได้อย่างไร

ฉันรู้เรื่องนอกเรื่อง แต่ถ้ามีคนที่สามารถอธิบายสิ่งนี้กับฉันได้ในรายละเอียดฉันก็จะขอบคุณมาก



นี่เป็นคำถามที่กว้างมาก หากคุณมีตัวอย่างเฉพาะของแบบสอบถามที่จะไม่ใช้ดัชนีและคุณไม่ทราบสาเหตุคุณสามารถโพสต์และคนอาจช่วยได้
Hammerite

SELECT * FROM members WHERE id = '1'- ทำไมดัชนีถึงทำงานเร็วขึ้น? ดัชนีนั้นทำอะไรที่นี่?
good_evening

2
ที่ดูเหมือนแบบสอบถามที่ค้นหาเฉพาะระเบียนที่จัดทำดัชนี (อาจระบุโดยคีย์หลัก) ดัชนีทำให้สิ่งนี้เร็วขึ้นเพราะเก็บไว้ในหน่วยความจำสามารถดูแถวดัชนีที่สอดคล้องกันและมีตัวชี้ไปยังที่ซึ่งข้อมูลจริงถูกเก็บไว้ ดังนั้น MySQL สามารถไปยังตำแหน่งที่แน่นอนในตารางโดยไม่ต้องสแกนตาราง
Hammerite

สบายดีมากขอบคุณ!
การแข่งขัน Lightness ใน Orbit

คำตอบ:


513

โดยทั่วไปดัชนีบนโต๊ะจะทำงานเหมือนกับดัชนีในหนังสือ (นั่นคือที่มาของชื่อ):

สมมติว่าคุณมีหนังสือเกี่ยวกับฐานข้อมูลและคุณต้องการค้นหาข้อมูลเกี่ยวกับพูดจัดเก็บข้อมูล หากไม่มีดัชนี (สมมติว่าไม่มีความช่วยเหลืออื่น ๆ เช่นสารบัญ) คุณจะต้องผ่านหน้าทีละหน้าจนกว่าคุณจะพบหัวข้อ (นั่นคือfull table scan) ในทางกลับกันดัชนีมีรายการคำหลักดังนั้นคุณควรศึกษาดัชนีและดูที่storageกล่าวถึงในหน้า 113-120,231 และ 354 จากนั้นคุณสามารถพลิกไปที่หน้าเหล่านั้นโดยตรงโดยไม่ต้องค้นหา (นั่นคือการค้นหาด้วย ดัชนีค่อนข้างเร็วขึ้น)

แน่นอนว่าดัชนีจะมีประโยชน์อย่างไรขึ้นอยู่กับหลาย ๆ อย่างตัวอย่างการใช้คำอุปมาข้างต้น

  • หากคุณมีหนังสือเกี่ยวกับฐานข้อมูลและจัดทำดัชนีคำว่า "ฐานข้อมูล" คุณจะเห็นว่ามันถูกกล่าวถึงในหน้า 1-59,61-290 และ 292 ถึง 400 ในกรณีเช่นนี้ดัชนีไม่ได้ช่วยอะไรมากนักและอาจ จะเร็วกว่าที่จะผ่านหน้าหนึ่งโดยหนึ่ง (ในฐานข้อมูลนี่คือ "การเลือกไม่ดี")
  • สำหรับหนังสือ 10 หน้ามันไม่มีเหตุผลที่จะสร้างดัชนีเพราะคุณอาจจบลงด้วยหนังสือ 10 หน้านำหน้าด้วยดัชนี 5 หน้าซึ่งโง่มาก - เพียงแค่สแกน 10 หน้าและทำมันให้เสร็จ .
  • ดัชนียังจำเป็นต้องมีประโยชน์โดยทั่วไปจะไม่มีการทำดัชนีเช่นความถี่ของตัวอักษร "L" ต่อหน้า

3
คุณกำลังอธิบายว่ามันคืออะไรไม่ใช่วิธีการทำงานทางเทคนิคภายใน
Tutu Kumari

@Tutu Kumari: ดูการแก้ไขคำถาม; อย่าลังเลที่จะแก้ไขคำตอบเพื่อให้เหมาะกับคำถามปัจจุบัน (สังเกตกลไกและประเภทดัชนีต่าง ๆ - ดูตัวอย่างเอกสารที่นี่: dev.mysql.com/doc/refman/8.0/en/index-btree-hash.html )
Piskvor ออกจากอาคาร

259

สิ่งแรกที่คุณต้องรู้คือดัชนีนั้นเป็นวิธีหนึ่งในการหลีกเลี่ยงการสแกนตารางเต็มเพื่อให้ได้ผลลัพธ์ที่คุณต้องการ

มีดัชนีประเภทต่าง ๆ และพวกมันถูกนำไปใช้ในเลเยอร์การจัดเก็บดังนั้นจึงไม่มีมาตรฐานระหว่างพวกเขาและพวกเขายังขึ้นอยู่กับเครื่องมือเก็บข้อมูลที่คุณใช้

InnoDB และดัชนี B + Tree

สำหรับ InnoDB ประเภทดัชนีที่พบบ่อยที่สุดคือดัชนีแบบอิง B + ซึ่งเก็บองค์ประกอบไว้ในลำดับที่เรียงลำดับ นอกจากนี้คุณไม่จำเป็นต้องเข้าถึงตารางจริงเพื่อรับค่าดัชนีซึ่งทำให้การสืบค้นของคุณกลับมาเร็วขึ้น

"ปัญหา" เกี่ยวกับประเภทดัชนีนี้คือคุณต้องค้นหาค่าซ้ายสุดเพื่อใช้ดัชนี ดังนั้นถ้าดัชนีของคุณมีสองคอลัมน์ last_name พูดและ first_name, คำสั่งซื้อที่คุณสอบถามข้อมูลเหล่านี้เป็นเรื่องสำคัญมาก

ดังนั้นให้ตารางต่อไปนี้:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

แบบสอบถามนี้จะใช้ประโยชน์จากดัชนี:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

แต่อย่างใดอย่างหนึ่งต่อไปนี้จะไม่

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

เนื่องจากคุณกำลังสืบค้นfirst_nameคอลัมน์ก่อนและไม่ใช่คอลัมน์ซ้ายสุดในดัชนี

ตัวอย่างสุดท้ายนี้ยิ่งแย่ลง:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

เพราะตอนนี้คุณกำลังเปรียบเทียบส่วนขวาสุดของฟิลด์ขวาสุดในดัชนี

ดัชนีแฮช

นี่เป็นดัชนีชนิดอื่นที่น่าเสียดายเฉพาะแบ็กเอนด์หน่วยความจำที่รองรับ มันเร็วฟ้าผ่า แต่เพียงมีประโยชน์สำหรับการค้นหาเต็มรูปแบบซึ่งหมายความว่าคุณไม่สามารถใช้งานได้สำหรับการดำเนินงานชอบ>, หรือ<LIKE

เนื่องจากมันใช้งานได้กับแบ็กเอนด์หน่วยความจำเท่านั้นคุณอาจจะไม่ใช้มันบ่อยนัก กรณีหลักที่ฉันนึกได้ตอนนี้คือตารางที่คุณสร้างตารางชั่วคราวในหน่วยความจำพร้อมชุดผลลัพธ์จากตัวเลือกอื่นและทำการเลือกอื่น ๆ จำนวนมากในตารางชั่วคราวนี้โดยใช้ดัชนีแฮช

หากคุณมีVARCHARเขตข้อมูลขนาดใหญ่คุณสามารถ "เลียนแบบ" การใช้ดัชนีแฮชเมื่อใช้ B-Tree โดยการสร้างคอลัมน์อื่นและบันทึกค่าที่มีค่ามาก สมมติว่าคุณกำลังเก็บ URL ในฟิลด์และค่ามีขนาดค่อนข้างใหญ่ คุณสามารถสร้างเขตข้อมูลจำนวนเต็มที่เรียกurl_hashและใช้ฟังก์ชันแฮชเช่นCRC32หรือฟังก์ชันแฮชอื่น ๆ เพื่อแฮช url เมื่อทำการแทรก จากนั้นเมื่อคุณต้องการสอบถามค่านี้คุณสามารถทำสิ่งนี้:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

ปัญหาของตัวอย่างข้างต้นคือเนื่องจากCRC32ฟังก์ชั่นสร้างแฮชขนาดเล็กมากคุณจะต้องเจอกับการชนจำนวนมากในค่าแฮช หากคุณต้องการค่าที่แน่นอนคุณสามารถแก้ไขปัญหานี้ได้โดยทำดังนี้

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

ยังคงมีค่าที่จะแฮชสิ่งต่าง ๆ แม้ว่าหมายเลขการชนจะสูงเพราะคุณจะทำการเปรียบเทียบครั้งที่สองเท่านั้น (สตริงที่หนึ่ง) กับแฮชซ้ำแล้วซ้ำอีก

น่าเสียดายที่ใช้เทคนิคนี้คุณยังต้องกดตารางเพื่อเปรียบเทียบurlฟิลด์

สรุป

ข้อเท็จจริงบางอย่างที่คุณอาจพิจารณาทุกครั้งที่คุณต้องการพูดคุยเกี่ยวกับการปรับให้เหมาะสม:

  1. การเปรียบเทียบจำนวนเต็มเร็วกว่าการเปรียบเทียบสตริง InnoDBมันสามารถแสดงตัวอย่างเกี่ยวกับการแข่งขันของกัญชาดัชนีใน

  2. อาจเพิ่มขั้นตอนเพิ่มเติมในกระบวนการทำให้เร็วขึ้นไม่ช้าลง มันสามารถแสดงให้เห็นได้จากข้อเท็จจริงที่ว่าคุณสามารถปรับ a ให้เหมาะสมSELECTโดยแยกออกเป็นสองขั้นตอนโดยสร้างค่าเก็บหนึ่งในตารางแรกในตารางหน่วยความจำที่สร้างขึ้นใหม่

MySQL มีดัชนีอื่น ๆ ด้วย แต่ผมคิดว่า B + ต้นไม้หนึ่งที่ใช้มากที่สุดที่เคยและกัญชาหนึ่งเป็นสิ่งที่ดีที่จะรู้ แต่คุณสามารถหาคนอื่น ๆ ในเอกสาร MySQL

ฉันขอแนะนำให้คุณอ่านหนังสือ "High Performance MySQL" คำตอบข้างต้นเป็นไปตามบทที่เกี่ยวกับดัชนีอย่างแน่นอน


2
แบบสอบถามต่อไปนี้จะมีประโยชน์ในกรณีข้างต้นหรือไม่ 1. SELECT last_name, first_name FROM person WHERE last_name= "Constantine" 2.SELECT last_name, first_name FROM person WHERE last_name LIKE "%Constantine"
Akshay Taru

1
Querry แรกจะค้นหาที่สองจะไม่ ใช้อธิบาย: dev.mysql.com/doc/refman/5.5/en/explain.html สำหรับการทำดัชนีเคียวรีที่สองด้วย MySQL คุณต้องใช้ FULLTEXT INDEX: dev.mysql.com/doc/refman/5.5/en/fulltext- search.html
Emilio Nicolás

5
ฉัน upvoting คุณเพราะคุณอยู่ที่ 127 และ # 1 คำตอบคือที่ 256 ฉันไม่สามารถหลีกเลี่ยงการทำทุกสิ่งที่ดีและสะอาดไบนารีฉลาด
pbarney

นี่เป็นข้อมูลใหม่สำหรับฉัน "สั่งให้คุณสืบค้นข้อมูลในฟิลด์เหล่านี้มีความสำคัญมาก" ขอบคุณ
Khatri

1
@pbarney หลังจากสามปีพวกเขาอยู่ใกล้ 256 และ 512 ตามลำดับนั่นคือสิ่งที่ฉันเรียกว่าการเพิ่มเลขฐานสอง!
nanocv

43

โดยทั่วไปดัชนีคือแผนที่ของกุญแจทั้งหมดของคุณที่เรียงลำดับ ด้วยรายการตามลำดับจากนั้นแทนที่จะตรวจสอบทุกคีย์มันสามารถทำสิ่งนี้:

1: ไปที่กลางรายการ - สูงหรือต่ำกว่าที่ฉันกำลังมองหา

2: ถ้าสูงกว่าให้ไปที่จุดกึ่งกลางระหว่างกลางและล่างถ้าต่ำกลางและบน

3: สูงหรือต่ำกว่า ข้ามไปที่จุดกึ่งกลางอีกครั้ง ฯลฯ

ใช้ตรรกะนั้นคุณสามารถค้นหาองค์ประกอบในรายการเรียงลำดับในประมาณ 7 ขั้นตอนแทนที่จะตรวจสอบทุกรายการ

เห็นได้ชัดว่ามีความซับซ้อน แต่นั่นทำให้คุณมีความคิดพื้นฐาน


29
สิ่งนี้เรียกว่าการค้นหาแบบไบนารี
ddlshack

ขอขอบคุณในที่สุดคำตอบที่อธิบายว่าทำไมมันเร็วกว่าและไม่ใช่แค่ว่า db ทำงานกับดัชนีอย่างไร
Gershon Herczeg

จำนวนขั้นตอนที่แท้จริงนั้นขึ้นอยู่กับข้อมูลเป็นอย่างมาก - จำนวนค่าที่ไม่ซ้ำกันและการกระจายข้ามช่วงของคุณ 7 เป็นค่าสูงสุดทางทฤษฎีสำหรับ 100 ค่า การอภิปรายเต็มรูปแบบของวิธีการคำนวณจำนวนขั้นตอนที่นี่stackoverflow.com/questions/10571170/…
Joshua

ดัชนี MySQL ที่พบมากที่สุดคือ B + Tree ซึ่งทำงานคล้ายกับการค้นหาแบบไบนารี แต่ไม่เหมือนกัน ความซับซ้อนของอัลกอริทึมเหมือนกัน แต่วิธีการค้นหานั้นไม่เหมือนกัน ดูen.wikipedia.org/wiki/B-tree
Matt

4

ลองดูที่ลิงค์นี้: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

วิธีการทำงานนั้นกว้างเกินกว่าที่จะครอบคลุมในโพสต์ SO หนึ่งรายการ

นี่คือหนึ่งในคำอธิบายที่ดีที่สุดของดัชนีที่ฉันได้เห็น น่าเสียดายที่มันมีไว้สำหรับ SQL Server และไม่ใช่ MySQL ฉันไม่แน่ใจว่าทั้งสองคล้ายกันอย่างไร ...


2
บทความที่ดี ฉันไม่รู้ SQL Server แต่การทำงานพื้นฐานดูคล้ายกันมาก (metanote: การปิดการใช้งานสไตล์ CSS ในบทความที่เชื่อมโยง 2
ปลด

3

ดูวิดีโอนี้สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการจัดทำดัชนี

การจัดทำดัชนีอย่างง่ายคุณสามารถสร้างดัชนีที่ไม่ซ้ำกันบนตาราง ดัชนีที่ไม่ซ้ำกันหมายความว่าสองแถวไม่สามารถมีค่าดัชนีเดียวกันได้ นี่คือไวยากรณ์ในการสร้างดัชนีบนโต๊ะ

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);

คุณสามารถใช้หนึ่งหรือหลายคอลัมน์เพื่อสร้างดัชนี ตัวอย่างเช่นเราสามารถสร้างดัชนีtutorials_tblโดยใช้ tutorial_author

CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)

คุณสามารถสร้างดัชนีอย่างง่ายบนตาราง เพียงละเว้นคำสำคัญ UNIQUE จากแบบสอบถามเพื่อสร้างดัชนีอย่างง่าย ดัชนีอย่างง่ายช่วยให้ค่าที่ซ้ำกันในตาราง

หากคุณต้องการทำดัชนีค่าในคอลัมน์ตามลำดับจากมากไปน้อยคุณสามารถเพิ่มคำสงวน DESC หลังชื่อคอลัมน์

mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)

1
ยินดีต้อนรับสู่ Stack Overflow! ฉันสังเกตว่าลิงก์คำตอบทั้งหมดของคุณไปยังวิดีโอของคุณเอง โปรดทราบว่าโปรโมชั่นด้วยตนเองโจ่งแจ้งไม่ได้รับอนุญาต
SL Barth - Reinstate Monica

เขาต้องการโปรโมตวิดีโอของเขา LOL
Ilyas karim

1

ฉันต้องการเพิ่ม 2 เซนต์ของฉัน ฉันยังห่างไกลจากการเป็นผู้เชี่ยวชาญด้านฐานข้อมูล แต่เมื่อเร็ว ๆ นี้ฉันได้อ่านหัวข้อนี้เล็กน้อย เพียงพอสำหรับฉันที่จะลองและมอบ ELI5 ดังนั้นนี่คือคำอธิบายของคนธรรมดา


ฉันเข้าใจว่าดัชนีเป็นเหมือนมินิมิเรอร์ของตารางของคุณซึ่งเหมือนกับอาร์เรย์ที่เชื่อมโยงกัน หากคุณป้อนด้วยคีย์ที่ตรงกันคุณก็สามารถข้ามไปยังแถวนั้นได้ใน "คำสั่ง" อันเดียว

แต่ถ้าคุณไม่มีดัชนี / แถวนั้นตัวแปลแบบสอบถามจะต้องใช้ for-loop เพื่อผ่านแถวทั้งหมดและตรวจสอบการจับคู่ (การสแกนแบบเต็มตาราง)

การมีดัชนีมี "ข้อเสีย" ของพื้นที่จัดเก็บเพิ่มเติม (สำหรับมินิมิเรอร์นั้น) เพื่อแลกกับ "ส่วนหัว" ของการค้นหาเนื้อหาได้เร็วขึ้น

โปรดทราบว่า (ขึ้นอยู่กับเอ็นจิ้น db ของคุณ) การสร้างคีย์หลักแปลกปลอมหรือคีย์เฉพาะจะตั้งค่าดัชนีตามลำดับโดยอัตโนมัติเช่นกัน หลักการเดียวกันนั้นเป็นเหตุผลว่าทำไมและกุญแจเหล่านั้นทำงานอย่างไร


1

การเพิ่มการแสดงภาพลงในรายการคำตอบ ป้อนคำอธิบายรูปภาพที่นี่

MySQL ใช้เลเยอร์ทางอ้อมเพิ่มเติม: เรคคอร์ดดัชนีรองชี้ไปที่เรคคอร์ดหลักและดัชนีหลักเองเก็บตำแหน่งของแถวบนดิสก์ หากมีการเปลี่ยนแปลงออฟเซ็ตแถวจะต้องอัปเดตเฉพาะดัชนีหลัก

Caveat: โครงสร้างข้อมูลดิสก์ดูเรียบในแผนภาพ แต่จริงๆแล้วเป็นต้นไม้ B +

แหล่งที่มา: ลิงค์


1

ใน MySQL InnoDB มีดัชนีสองประเภท

  1. คีย์หลักซึ่งเรียกว่าดัชนีคลัสเตอร์ คำสำคัญของดัชนีถูกเก็บไว้พร้อมกับข้อมูลบันทึกจริงในโหนด B + Tree leaf

  2. คีย์รองซึ่งไม่ใช่ดัชนีแบบคลัสเตอร์ ดัชนีเหล่านี้เก็บคำสำคัญของคีย์หลักเท่านั้นพร้อมกับคำสำคัญดัชนีของตนเองในโหนด B + Tree leaf ดังนั้นเมื่อค้นหาจากดัชนีรองอันดับแรกจะค้นหาคำสำคัญของดัชนีคีย์หลักและสแกนคีย์หลัก B + Tree เพื่อค้นหาระเบียนข้อมูลจริง สิ่งนี้จะทำให้ดัชนีรองช้ากว่าการค้นหาดัชนีหลัก อย่างไรก็ตามหากselectคอลัมน์ทั้งหมดอยู่ในดัชนีรองคุณไม่จำเป็นต้องค้นหาดัชนี B + Tree อีกครั้ง สิ่งนี้เรียกว่าการครอบคลุมดัชนี

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