นี่คือสถานการณ์ที่เกิดขึ้นเมื่อไม่นานมานี้ในที่ทำงาน
พิจารณาสามตาราง A, B, C
A มี 3,000 แถว; B มี 300,000,000 แถว; และ C มี 2,000 แถว
มีการกำหนดคีย์ต่างประเทศ: B (a_id), B (c_id)
สมมติว่าคุณมีข้อความค้นหาที่มีลักษณะดังนี้:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
จากประสบการณ์ของฉัน MySQL อาจเลือกไปที่ C -> B -> A ในกรณีนี้ C มีขนาดเล็กกว่า A และ B นั้นมีค่ามหาศาลและพวกมันทั้งหมดเป็น Equijoins
ปัญหาคือ MySQL ไม่จำเป็นต้องคำนึงถึงขนาดของจุดตัดระหว่าง (C.id และ B.c_id) เทียบกับ (A.id และ B.a_id) ถ้าการรวมระหว่าง B และ C ส่งคืนแถวเท่า ๆ กับ B แสดงว่าเป็นตัวเลือกที่แย่มาก ถ้าเริ่มต้นด้วย A จะกรอง B ลงให้มากที่สุดเท่าที่ A แถวนั้นจะเป็นทางเลือกที่ดีกว่า straight_join
สามารถใช้บังคับคำสั่งนี้ได้ดังนี้:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
ตอนนี้ต้องสามารถเข้าร่วมก่อนa
b
โดยทั่วไปคุณต้องการทำการรวมของคุณตามลำดับที่ลดจำนวนแถวในชุดผลลัพธ์ ดังนั้นการเริ่มต้นด้วยโต๊ะเล็ก ๆ และการเข้าร่วมเพื่อให้การรวมที่เกิดขึ้นจะมีขนาดเล็กด้วยจึงเหมาะอย่างยิ่ง สิ่งต่าง ๆ จะกลายเป็นรูปลูกแพร์หากเริ่มต้นด้วยโต๊ะเล็ก ๆ และรวมเข้ากับโต๊ะที่ใหญ่กว่าจะมีขนาดใหญ่เท่ากับโต๊ะตัวใหญ่
สถิติขึ้นอยู่กับว่า หากการกระจายข้อมูลเปลี่ยนแปลงการคำนวณอาจเปลี่ยนแปลง นอกจากนี้ยังขึ้นอยู่กับรายละเอียดการใช้งานของกลไกการเข้าร่วม
กรณีที่เลวร้ายที่สุดที่ฉันเคยเห็นสำหรับ MySQL straight_join
การบอกใบ้ดัชนีทั้งหมดยกเว้นที่จำเป็นหรือเชิงรุกคือข้อความค้นหาที่แบ่งหน้าข้อมูลจำนวนมากตามลำดับการจัดเรียงที่เข้มงวดพร้อมการกรองแสง MySQL ต้องการใช้ดัชนีสำหรับตัวกรองใด ๆ และเข้าร่วมในประเภทต่างๆ สิ่งนี้สมเหตุสมผลเพราะคนส่วนใหญ่ไม่ได้พยายามจัดเรียงฐานข้อมูลทั้งหมด แต่มีแถวย่อยที่ จำกัด ที่ตอบสนองต่อแบบสอบถามและการจัดเรียงชุดย่อยที่ จำกัด นั้นเร็วกว่าการกรองทั้งตารางไม่ว่าจะเรียงลำดับหรือ ไม่. ในกรณีนี้การรวมแบบตรงทันทีหลังตารางที่มีคอลัมน์ที่จัดทำดัชนีที่ฉันต้องการจัดเรียงตามสิ่งที่ตายตัว
straight_join
ใด