การใช้ Index ร่วมกับ $or Operator ใน MongoDB
ใช่ สามารถใช้ Index ได้เมื่อ Query มี $or operator โดย MongoDB จะใช้ Index สำหรับแต่ละเงื่อนไขใน $or แยกกัน แล้วรวมผลลัพธ์เข้าด้วยกัน
การสร้าง Index
> db.indexOrQueryDemo.ensureIndex({"First":1});
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 2, "numIndexesAfter" : 3, "ok" : 1 }
> db.indexOrQueryDemo.ensureIndex({"Second":1});
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 3, "numIndexesAfter" : 4, "ok" : 1 }
การ Query ด้วย $or และตรวจสอบด้วย explain()
> db.indexOrQueryDemo.find({$or:[{First:1}, {Second:2}]}).explain();
ผลลัพธ์ explain() (สรุปสำคัญ)
{
"queryPlanner" : {
"winningPlan" : {
"stage" : "SUBPLAN",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "OR",
"inputStages" : [
{
"stage" : "IXSCAN",
"keyPattern" : { "First" : 1 },
"indexName" : "First_1",
"indexBounds" : { "First" : [ "[1.0, 1.0]" ] }
},
{
"stage" : "IXSCAN",
"keyPattern" : { "Second" : 1 },
"indexName" : "Second_1",
"indexBounds" : { "Second" : [ "[2.0, 2.0]" ] }
}
]
}
}
}
},
"ok" : 1
}
คำอธิบายจาก Execution Plan
- IXSCAN (Index Scan) : MongoDB ใช้ Index Scan สำหรับแต่ละเงื่อนไขใน $or (First_1 และ Second_1)
- OR Stage : รวมผลลัพธ์จากทั้งสอง Index Scan เข้าด้วยกัน
- FETCH : ดึงเอกสารเต็มจาก collection ตาม _id ที่ได้จาก Index
ข้อสังเกตสำคัญ
- แต่ละเงื่อนไขใน $or ต้องมี Index ของตัวเอง - MongoDB ไม่สามารถใช้ compound index เดียวสำหรับ $or ทั้งหมดได้ (ยกเว้นกรณีพิเศษ)
- Index Intersection : MongoDB อาจใช้หลาย Index แยกกันแล้วรวมผล (Index Intersection) ในบางกรณี
- ประสิทธิภาพ : $or ที่มีหลายเงื่อนไขอาจช้ากว่า query ธรรมดา เนื่องจากต้องสแกนหลาย Index
แนวทางปฏิบัติที่ดี (Best Practices)
- สร้าง Index ให้ครบทุกฟิลด์ที่ใช้ใน $or
- ใช้
explain("executionStats")เพื่อตรวจสอบว่า Index ถูกใช้งานจริง - พิจารณา restructure schema หาก $or ใช้บ่อยและซับซ้อน
- หลีกเลี่ยง $or ที่มีเงื่อนไขเยอะมาก (>10 clauses)
หมายเหตุ: ensureIndex() ถูก deprecated แล้ว ควรใช้ createIndex() แทนใน MongoDB เวอร์ชันใหม่