ดัชนี MySQL - แนวปฏิบัติที่ดีที่สุดคืออะไร


208

ฉันใช้ดัชนีในฐานข้อมูล MySQL มาระยะหนึ่งแล้ว แต่ไม่เคยเรียนรู้มาก่อน โดยทั่วไปแล้วฉันวางดัชนีลงในเขตข้อมูลใด ๆ ที่ฉันจะค้นหาหรือเลือกโดยใช้WHEREประโยค

แนวปฏิบัติที่ดีที่สุดสำหรับดัชนี MySQL คืออะไร

ตัวอย่างสถานการณ์ / ประเด็นขัดแย้ง:

  • หากตารางมีหกคอลัมน์และทั้งหมดสามารถค้นหาได้ฉันควรจัดทำดัชนีทั้งหมดหรือไม่?

  • ประสิทธิภาพเชิงลบของการจัดทำดัชนีคืออะไร

  • หากฉันมีคอลัมน์ VARCHAR 2500 ซึ่งสามารถค้นหาได้จากบางส่วนของเว็บไซต์ของฉันฉันควรสร้างดัชนีหรือไม่


5
คุณน่าจะลองถามคำถามอีกครั้ง ตัวเลือกของดัชนีเป็นส่วนสำคัญสำหรับการปรับรุ่นฐานข้อมูลใด ๆ และในมุมมองของฉันไม่เกี่ยวข้องกับ PHP
VGE


คำตอบ:


242

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

การพูดแบบกว้าง ๆ ดัชนีจะกำหนดลำดับของแถวของตาราง

เพื่อความเรียบง่ายลองจินตนาการว่าตารางเป็นเพียงไฟล์ CSV ขนาดใหญ่ เมื่อใดก็ตามที่มีแทรกแถวก็แทรกในตอนท้าย ดังนั้นการเรียงลำดับแบบ "ธรรมชาติ" ของตารางจึงเป็นเพียงลำดับในการแทรกแถว

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

ทีนี้ลองนึกภาพว่าคุณต้องหาแถวทั้งหมดที่มีค่า "M" ในคอลัมน์ที่สาม เมื่อพิจารณาจากสิ่งที่คุณมีอยู่คุณมีเพียงหนึ่งตัวเลือก คุณสแกนตารางตรวจสอบค่าของคอลัมน์ที่สามสำหรับแต่ละแถว หากคุณมีจำนวนมากแถววิธีนี้ ("สแกนตาราง") อาจใช้เวลานาน!

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

ตอนนี้คุณมีกลยุทธ์ที่ดีสำหรับการค้นหาแถวทั้งหมดที่ค่าของคอลัมน์ที่สามคือ "M" ตัวอย่างเช่นคุณสามารถทำการค้นหาแบบไบนารี ! ในขณะที่การสแกนตารางต้องการให้คุณมองแถว N (โดยที่ N คือจำนวนแถว) การค้นหาแบบไบนารีจะกำหนดให้คุณดูรายการดัชนี log-n เท่านั้นในกรณีที่แย่ที่สุด ว้าวแน่นอนว่าง่ายกว่าเยอะ!

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

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

ในทางกลับกันการอ่านจะเร็วขึ้นมาก

หวังว่าจะครอบคลุมคำถามสองข้อแรกของคุณ (อย่างที่คนอื่นตอบแล้วคุณต้องหายอดที่เหมาะสม)

สถานการณ์ที่สามของคุณซับซ้อนกว่าเล็กน้อย หากคุณใช้ LIKE เครื่องมือสร้างดัชนีจะช่วยให้คุณอ่านได้เร็วขึ้นถึง "%" ตัวแรก กล่าวอีกนัยหนึ่งหากคุณกำลังเลือกคอลัมน์ที่ต้องการ 'foo% bar%' ฐานข้อมูลจะใช้ดัชนีเพื่อค้นหาแถวทั้งหมดที่คอลัมน์เริ่มต้นด้วย "foo" แล้วต้องสแกน rowset ระดับกลางนั้นเพื่อค้นหาชุดย่อย ที่มี "บาร์" เลือก ... คอลัมน์ที่ต้องการ '% bar%' ไม่สามารถใช้ดัชนีได้ ฉันหวังว่าคุณจะเห็นเหตุผล

สุดท้ายคุณต้องเริ่มคิดเกี่ยวกับดัชนีในคอลัมน์มากกว่าหนึ่งคอลัมน์ แนวคิดนั้นเหมือนกันและมีพฤติกรรมคล้ายกับสิ่งของ LIKE - โดยพื้นฐานแล้วหากคุณมีดัชนีใน (a, b, c) เครื่องยนต์จะใช้ดัชนีจากซ้ายไปขวาอย่างต่อเนื่องเท่าที่จะทำได้ ดังนั้นการค้นหาในคอลัมน์ a อาจใช้ดัชนี (a, b, c) เช่นเดียวกับใน (a, b) อย่างไรก็ตามเอ็นจิ้นจะต้องทำการสแกนแบบเต็มตารางหากคุณค้นหา WHERE b = 5 AND c = 1)

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


10
แล้วFULLTEXTดัชนีล่ะ พวกเขาสามารถช่วยด้วยเงื่อนไขเช่นLIKE '%bar%'?
ก.ย. 30

2
@Septagram - FULLTEXTสามารถช่วยให้มีที่แบบสอบถามถ้า barเป็น "คำว่า" FULLTEXTจัดการกับคำไม่ใช่สารตั้งต้น (เช่นเดียวกับLIKE)
Rick James

@timdev อย่างชัดเจนในส่วนใดที่ตอบคำถามแรก ฉันสามารถตรวจสอบคำถามที่สองและสามที่ได้รับคำตอบในส่วนที่หนึ่งและที่สอง (ก่อนและหลังของหวังว่าจะครอบคลุมคำถามสองข้อแรกของคุณ ) ของคำตอบที่มีค่าของคุณ
Manuel Jordan

1
@ManuelJordan - ไม่มีคำตอบง่ายๆสำหรับคำถามแรก ขึ้นอยู่กับว่าคุณต้องการสร้างความสมดุลให้กับการแลกเปลี่ยนในบริบทของการใช้งานที่คาดการณ์ไว้
timdev

57

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

Update 12/2012: ฉันได้โพสต์งานนำเสนอใหม่ของฉัน: วิธีการออกแบบดัชนี, จริงๆ ฉันเสนอสิ่งนี้ในเดือนตุลาคม 2012 ที่ ZendCon ในซานตาคลาร่าและในเดือนธันวาคม 2012 ที่ Percona Live London

การออกแบบดัชนีที่ดีที่สุดคือกระบวนการที่ต้องจับคู่คำค้นหาที่คุณเรียกใช้ในแอพของคุณ

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

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

สำหรับคอลัมน์ที่เป็น VARCHAR (2500) คุณอาจต้องการใช้ดัชนี FULLTEXTหรือดัชนีคำนำหน้า:

CREATE INDEX i ON SomeTable(longVarchar(100));

โปรดทราบว่าดัชนีทั่วไปไม่สามารถช่วยได้หากคุณกำลังค้นหาคำที่อาจอยู่ในช่วงกลางของ varchar ที่ยาว สำหรับสิ่งนั้นให้ใช้ดัชนี fulltext


3
ขอบคุณมาก. slideshare.net/matsunobu/…มีประโยชน์มากแน่นอน
Bishal Paudel

slideshare.net/billkarwin/how-to-design-indexes-really slideshare.net/matsunobu/...ทั้งการเชื่อมโยงไม่ได้ทำงาน
ankur

1
ยอดเยี่ยม the slideshare.net/billkarwin/how-to-design-indexes-really Presentation
Manuel Jordan

1
การนำเสนอที่น่าตื่นตาตื่นใจ (หนึ่งจาก 2012) เข้าใจจุดทั้งหมดของดัชนีอย่างแท้จริง
DarkteK

46

ฉันจะไม่ทำซ้ำคำแนะนำที่ดีในคำตอบอื่น ๆ แต่จะเพิ่ม:

ดัชนีผสม

คุณสามารถสร้างดัชนีผสม - ดัชนีที่มีหลายคอลัมน์ MySQL สามารถใช้เหล่านี้จากซ้ายไปขวา ดังนั้นถ้าคุณมี:

Table A
Id
Name
Category
Age
Description

หากคุณมีดัชนีรวมที่มีชื่อ / หมวดหมู่ / อายุในลำดับนั้นคำสั่ง WHERE เหล่านี้จะใช้ดัชนี:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

แต่

WHERE Category='A' and Age > 18

จะไม่ใช้ดัชนีนั้นเพราะทุกอย่างจะต้องใช้จากซ้ายไปขวา

อธิบาย

ใช้อธิบาย / อธิบายเพิ่มเติมเพื่อทำความเข้าใจว่าดัชนีใดที่มีอยู่ใน MySQL และดัชนีใดที่เลือกไว้ MySQL จะใช้อย่างใดอย่างหนึ่งที่สำคัญต่อข้อความ

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

บันทึกข้อความค้นหาช้า

เปิดบันทึกการสืบค้นที่ช้าเพื่อดูว่าการสืบค้นใดที่ทำงานช้า

คอลัมน์กว้าง

หากคุณมีคอลัมน์กว้างที่มีความแตกต่างมากที่สุดเกิดขึ้นในอักขระตัวแรกหลายตัวคุณสามารถใช้อักขระ N ตัวแรกในดัชนีของคุณเท่านั้น ตัวอย่าง: เรามีคอลัมน์ ReferenceNumber ที่กำหนดเป็น varchar (255) แต่ 97% ของเคสหมายเลขอ้างอิงคือ 10 อักขระหรือน้อยกว่า ฉันเปลี่ยนดัชนีให้ดูเฉพาะอักขระ 10 ตัวแรกและปรับปรุงประสิทธิภาพให้ดีขึ้นเล็กน้อย


ฉันมีคำถามเกี่ยวกับส่วนสุดท้าย ฉันอ่านบางที่ว่าถ้าคุณสร้างคอลัมน์ด้วย VARCHAR คุณควรตั้งไว้ที่ 255 เสมอตอนนี้คุณบอกว่าดัชนีที่ตั้งค่าไว้ที่คอลัมน์ประเภทนี้อาจถูก จำกัด ให้ดูเฉพาะอักขระ 10 ตัวแรกเท่านั้น คุณจะทำอย่างนั้นได้อย่างไร?
AlexioVay

20

หากตารางมีหกคอลัมน์และทุกคอลัมน์สามารถค้นหาได้ฉันควรสร้างดัชนีทั้งหมดหรือไม่แสดงเลย

คุณค้นหาในฟิลด์ตามฟิลด์หรือบางการค้นหาใช้หลายฟิลด์? ฟิลด์ใดที่ถูกค้นหามากที่สุด ฟิลด์ประเภทใด (ดัชนีทำงานได้ดีบน INTs มากกว่าบน VARCHARs) คุณลองใช้ EXPLAIN กับข้อความค้นหาที่กำลังทำงานอยู่หรือไม่

ประสิทธิภาพเชิงลบมีผลกระทบอะไรบ้างต่อการจัดทำดัชนี

การอัปเดตและ INSERT จะช้าลง นอกจากนี้ยังมีข้อกำหนดพื้นที่เก็บข้อมูลเพิ่มเติม แต่วันนี้ไม่สำคัญ

หากฉันมีคอลัมน์ VARCHAR 2500 ซึ่งสามารถค้นหาได้จากส่วนต่างๆของเว็บไซต์ของฉันฉันควรสร้างดัชนีหรือไม่

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

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

ปกติแล้วฉันจะสร้างดัชนีฟิลด์ที่มีการสอบถามมากที่สุดและจากนั้น INTs / บูลีน / Enum แทนที่จะเป็นฟิลด์ที่เป็น VARCHARS อย่าลืมบ่อยครั้งที่คุณต้องสร้างดัชนีในเขตข้อมูลที่รวมกันแทนที่จะเป็นดัชนีในแต่ละเขตข้อมูล ใช้อธิบายและตรวจสอบบันทึกช้า


11

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

หลีกเลี่ยงดัชนี : หากคุณไม่ต้องการดัชนีเฉพาะเพื่อช่วยให้แบบสอบถามทำงานได้ดีขึ้นอย่าสร้างดัชนี

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

Takeaway: อย่าเกินดัชนี


5

โดยทั่วไปดัชนีช่วยค้นหาฐานข้อมูลที่รวดเร็วโดยมีข้อเสียของการใช้พื้นที่ดิสก์เพิ่มเติมและการชะลอตัวINSERT/ UPDATE/ DELETEแบบสอบถาม ใช้EXPLAINและอ่านผลลัพธ์เพื่อค้นหาว่า MySQL ใช้ดัชนีของคุณเมื่อใด

หากตารางมีหกคอลัมน์และทุกคอลัมน์สามารถค้นหาได้ฉันควรสร้างดัชนีทั้งหมดหรือไม่ได้เลย

การทำดัชนีทั้งหกคอลัมน์ไม่ใช่วิธีที่ดีที่สุดเสมอไป

(a) คุณจะใช้คอลัมน์ใดคอลัมน์หนึ่งเหล่านี้เมื่อค้นหาข้อมูลเฉพาะหรือไม่

(b) อะไรคือการเลือกของคอลัมน์เหล่านั้น (จำนวนค่าที่แตกต่างกันจะถูกเก็บไว้เมื่อเทียบกับจำนวนรวมของการบันทึกบนโต๊ะ)?

MySQL ใช้เครื่องมือเพิ่มประสิทธิภาพต้นทุนซึ่งพยายามค้นหาเส้นทางที่ "ถูกที่สุด" เมื่อทำการค้นหา และเขตข้อมูลที่มีการเลือกต่ำไม่ใช่ผู้สมัครที่ดี

ประสิทธิภาพเชิงลบของการจัดทำดัชนีคืออะไร

ตอบแล้ว: พื้นที่ดิสก์เพิ่มเติมประสิทธิภาพลดลงในระหว่างการแทรก - อัพเดต - ลบ

หากฉันมีคอลัมน์ VARCHAR 2500 ซึ่งสามารถค้นหาได้จากส่วนต่างๆของเว็บไซต์ของฉันฉันควรสร้างดัชนีหรือไม่

ลองดัชนี FULLTEXT


4

1/2) ดัชนีเร่งความเร็วการดำเนินการบางอย่างที่เลือก แต่มันช้าลงการดำเนินการอื่น ๆ เช่นการแทรกการปรับปรุงและการลบ สามารถปรับสมดุลได้

3) ใช้ดัชนีข้อความแบบเต็มหรือบางทีอาจเป็นสฟิงซ์


เพื่อป้องกันslow down other operations like insert, update and deletesคุณสามารถใช้START TRANSACTION; YOUR CODE HERE; COMMIT ซึ่งสามารถช่วยหลีกเลี่ยงslowing downการดำเนินการอื่น ๆ เพราะมันจะตรวจสอบข้อ จำกัด เพียงครั้งเดียว CAVEAT: ถ้าคุณใช้REPLACE INTOของคุณและSQL_MODE<> STRICT_ALL_TABLESหรือจะไม่สนใจแทนที่เข้าและแทรกซ้ำกัน TRADITIONALBulk Load
JayRizzo

ธุรกรรมไม่ได้รับการสนับสนุนในเครื่องมือ MySQL ทั้งหมด AFAIK ธุรกรรมที่ทำให้การดำเนินงานฐานข้อมูลช้าลงแม้ว่าพวกเขาจะถูกใช้โดยปริยายเท่านั้น สิ่งที่เราต้องออกแบบตามประสิทธิภาพที่แท้จริงคือวิธีการทำโปรไฟล์โดยอัตโนมัติแบบกึ่งอัตโนมัติ (วัดประสิทธิภาพ) ของตัวเลือกการเพิ่มประสิทธิภาพที่หลากหลายรวมถึงดัชนีและธุรกรรม
David Spector
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.