Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

วิธีปรับปรุงประสิทธิภาพ Query Field ใน MongoDB

การปรับปรุงประสิทธิภาพ Query Field ใน MongoDB ด้วย Index

สร้าง Index บนฟิลด์ที่ Query บ่อย เพื่อเพิ่มความเร็วในการค้นหา โดยเฉพาะฟิลด์ภายใน Array (Nested Array Fields)

ตัวอย่างการสร้างคอลเลกชันและเพิ่มข้อมูล (Array of Objects)

> db.improveQueryDemo.insertOne({ 
    "PlayerDetails": [ 
        {"PlayerName": "John", "PlayerGameScore": 5690}, 
        {"PlayerName": "Carol", "PlayerGameScore": 2690} 
    ] 
});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9dbaf875e2eeda1d5c3670") }

แสดงข้อมูล

> db.improveQueryDemo.find().pretty();

ผลลัพธ์:

{ 
    "_id" : ObjectId("5c9dbaf875e2eeda1d5c3670"), 
    "PlayerDetails" : [ 
        { "PlayerName" : "John", "PlayerGameScore" : 5690 }, 
        { "PlayerName" : "Carol", "PlayerGameScore" : 2690 } 
    ] 
}

สร้าง Index บน Nested Field ใน Array

> db.improveQueryDemo.ensureIndex({"PlayerDetails.PlayerName": 1});
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }

หมายเหตุ: ensureIndex() ถูก Deprecated แล้ว ควรใช้ createIndex()

Query ด้วย Exact Match บน Nested Field

> db.improveQueryDemo.find({"PlayerDetails.PlayerName": "Carol"}).pretty();

ผลลัพธ์ (คืน Document ทั้งหมดที่ Array มี Element match):

{ 
    "_id" : ObjectId("5c9dbaf875e2eeda1d5c3670"), 
    "PlayerDetails" : [ 
        { "PlayerName" : "John", "PlayerGameScore" : 5690 }, 
        { "PlayerName" : "Carol", "PlayerGameScore" : 2690 } 
    ] 
}

คำอธิบาย Index บน Array Field

  • Multikey Index: MongoDB สร้าง Index Entry สำหรับ ทุก Element ใน Array อัตโนมัติ
  • Index Key: "PlayerDetails.PlayerName" -> Index จะมี Entry สำหรับ "John" และ "Carol" แยกกัน
  • Query Match: หา "Carol" -> Index ชี้ไปที่ Document นี้ได้ทันที

การตรวจสอบว่า Index ถูกใช้งาน (explain)

> db.improveQueryDemo.find({"PlayerDetails.PlayerName": "Carol"}).explain("executionStats");

สัญญาณว่า Index ทำงาน: "stage": "IXSCAN" (Index Scan) แทน "COLLSCAN" (Collection Scan)

ข้อจำกัดของ Multikey Index

  • ไม่สามารถสร้าง Compound Multikey Index ได้มากกว่า 1 Array Field
  • { "PlayerDetails.PlayerName": 1, "PlayerDetails.PlayerGameScore": 1 } -> OK (Array เดียวกัน)
  • { "Array1.field": 1, "Array2.field": 1 } -> ❌ Error: "cannot index parallel arrays"

Best Practices สำหรับ Index Optimization

1. สร้าง Index ตรงกับ Query Pattern

// Query: find({ "PlayerDetails.PlayerName": "Carol" })
// Index: { "PlayerDetails.PlayerName": 1 } ✅

// Query: find({ "PlayerDetails.PlayerName": "Carol", "PlayerDetails.PlayerGameScore": { $gt: 3000 } })
// Index: { "PlayerDetails.PlayerName": 1, "PlayerDetails.PlayerGameScore": 1 } ✅

2. ใช้ explain() วิเคราะห์ Query Plan

db.collection.find(query).explain("executionStats")

ดู winningPlan.stage : IXSCAN = ใช้ Index, COLLSCAN = Full Scan

3. หลีกเลี่ยง Index มากเกินไป

  • แต่ละ Index ใช้ RAM และ Disk Space
  • เขียน (Insert/Update/Delete) ช้าลงตามจำนวน Index
  • Limit: 64 Indexes per Collection

4. ใช้ Partial Index (MongoDB 3.2+) สำหรับ Subset

db.collection.createIndex(
    { "PlayerDetails.PlayerName": 1 }, 
    { partialFilterExpression: { "PlayerDetails.PlayerGameScore": { $gt: 1000 } } }
);

5. TTL Index สำหรับข้อมูลหมดอายุ

db.logs.createIndex({ "createdAt": 1 }, { expireAfterSeconds: 2592000 }); // 30 days

สรุป

  • สร้าง Index บน Field ที่ Query บ่อย (Equality, Sort, Range)
  • Array Field -> Multikey Index อัตโนมัติ
  • ใช้ createIndex() แทน ensureIndex()
  • ตรวจสอบด้วย explain("executionStats") ทุกครั้งหลังสร้าง Index
  • Monitor Index Usage: db.collection.aggregate([{$indexStats: {}}])