การออกแบบ index ที่ดี เป็น กุญแจสำคัญในการเพิ่มประสิทธิภาพการค้นหาข้อมูลใน MongoDB โดยเฉพาะอย่างยิ่งเมื่อมีการใช้งาน index แบบผสม (Compound Index) ที่ประกอบด้วยหลายฟิลด์ในคีย์เดียว ESR Guideline จึงถูกพัฒนาขึ้นมาเพื่อเป็นแนวทางในการจัดเรียงลำดับของ index key อย่างเป็นระบบ
โดยยึดหลัก Equality → Sort → Range ซึ่งช่วยลดภาระการประมวลผล และเร่งความเร็วของการค้นหาอย่างมีนัยสำคัญ
ทำไมถึงต้องใช้ ESR Guideline
- ลดเวลาในการค้นหา: Compound Index ที่จัดเรียงอย่างถูกต้องช่วยให้ค้นหาได้เร็วขึ้นมาก
- ลดการใช้หน่วยความจำ: ใช้ Index Sort แทน in-memory sort ได้
- ลดภาระในการสแกนเอกสาร: การใช้ Equality ก่อนช่วยลดจำนวนเอกสารที่ MongoDB ต้องตรวจสอบ
- เพิ่มความแม่นยำในการสร้าง index: แนวทาง ESR ทำให้การออกแบบ index มีโครงสร้างที่ชัดเจนและเป็นระบบ
ESR Guideline
เรามาดูแต่ละตัวกันเลย...
1. Equality (E) – ความเท่าเทียม
เงื่อนไขแบบเท่าเทียมกัน (exact match) เช่น { field: "value" }
เป็นเงื่อนไขที่ควรได้รับความสำคัญสูงสุดในการจัดเรียง index key:
db.cars.find( { model: "Cordoba" } )
db.cars.find( { model: { $eq: "Cordoba" } } )
โดยสิ่งที่เราต้องทำ คือ
- ควรวางฟิลด์เหล่านี้ไว้ ลำดับต้นๆ ของ index
- index สามารถมีหลาย key ที่เป็น exact match โดยไม่ต้องเรียงลำดับระหว่างกัน แต่ทั้งหมดต้องมาก่อนฟิลด์อื่นๆ
- ควรเลือกใช้เงื่อนไขที่ selective (มีความคัดเลือกสูง) เพื่อกรองข้อมูลให้แคบลงตั้งแต่ต้น เช่น ช่วยลดเอกสารที่ต้องตรวจสอบได้อย่างน้อย 90%
- ตัวดำเนินการ
$in
ถือว่าเป็น exact match เมื่อใช้กับอาร์เรย์ที่มีน้อยกว่า 200 ค่า - ขณะที่ตัวดำเนินการอย่าง
$ne
,$nin
และ$regex
ไม่ถือเป็น Equality แต่เป็น Range
2. Sort (S) – การเรียงลำดับ
เงื่อนไขการเรียงลำดับควรถูกจัดไว้ หลังฟิลด์ Equality เพื่อให้ MongoDB สามารถใช้ Index Sort แทนการ sort ด้วยหน่วยความจำ:
สิ่งที่ต้องทำ คือ
- ฟิลด์สำหรับการ sort ควรอยู่ใน index key หลังจากฟิลด์ที่เป็น Equality
- ควรระบุลำดับการเรียง (1 สำหรับน้อยไปมาก, -1 สำหรับมากไปน้อย) ให้ ตรงกันกับการค้นหา
- การเรียงลำดับจะใช้ index ได้อย่างมีประสิทธิภาพ เมื่อเงื่อนไขการค้นหา ครอบคลุม prefix ของ index
ตัวอย่างเช่น
ถ้าเรามีการค้นหาข้อมูลผู้ผลิตรถยนต์ และต้องการ sort ตัว model ของรถยนต์ จากน้อยไปมาก ด้วยแบบนี้
db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )
เราควรที่จะ improve query performance ของ index โดยการสร้าง index manufacturer
and model
db.cars.createIndex( { manufacturer: 1, model: 1 } )
3. Range (R) – การกรองช่วง
เงื่อนไขแบบช่วง เช่น { price: { $gt: 10000 } }
จะไม่สามารถใช้ Index Sort ได้ หากอยู่ก่อนในลำดับ index จะทำให้ประสิทธิภาพลดลง
db.cars.find( { price: { $gte: 15000} } )
db.cars.find( { age: { $lt: 10 } } )
db.cars.find( { priorAccidents: { $ne: null } } )
สิ่งที่ต้องทำ คือ
- ตัวกรองช่วงควรวาง ท้ายสุด ของลำดับ index key
- ตัวดำเนินการ Range ได้แก่
$gt
,$lt
,$gte
,$ne
,$regex
เป็นต้น - การใช้ฟิลด์ Range อย่างมีกลยุทธ์ร่วมกับ Equality และ Sort ช่วยเพิ่มประสิทธิภาพโดยรวมของการค้นหาได้มาก
ตัวอย่างการใช้งาน ESR Guideline
ทีนี้เรามาดูตัวอย่างการใช้งานกัน สมมุติว่าเราต้องการค้นหารถยนต์ที่:
- ผู้ผลิตเป็น “Ford”
- ราคาเกิน $15,000
- เรียงตามชื่อรุ่น
การ query หน้าตาจะเป็นแบบนี้
db.cars.find(
{
manufacturer: 'Ford',
cost: { $gt: 15000 }
} ).sort( { model: 1 } )
ในการสร้าง Index เราควรใช้แบบนี้ คือ
{ manufacturer: 1, model: 1, cost: 1 }
โดยที่
manufacturer
= Equalitymodel
= Sortcost
= Range
ลำดับนี้สอดคล้องกับ ESR Guideline อย่างชัดเจน