การออกแบบ 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 = Equality
  • model = Sort
  • cost = Range

ลำดับนี้สอดคล้องกับ ESR Guideline อย่างชัดเจน


References