แบบสอบถามช้าใน MongoDB พร้อมแบบสอบถามรวมคอลเลกชันกว้างโดยใช้กลุ่ม

ฉันประสบปัญหาด้านประสิทธิภาพบน API ที่ฉันกำลังพัฒนาโดยใช้ NodeJS+Express+MongoDB

ในการรันการรวมด้วย $match กับผลิตภัณฑ์ใดผลิตภัณฑ์หนึ่ง ประสิทธิภาพดี แต่สำหรับการค้นหาแบบเปิดจะช้ามาก

ฉันต้องการเรียกใช้กลุ่มในสองคอลัมน์: ประเทศและผู้ส่งออก จากนั้นดึงผลลัพธ์ที่จำกัดไว้ที่ 3 ผลลัพธ์ต่อกลุ่มในประเทศ

ข้อกำหนด: จำนวนรวมของผู้ส่งออกที่ไม่ซ้ำกันจากแต่ละประเทศ พร้อมด้วยบันทึก 3 รายการจากแต่ละประเทศ

เมื่อรัน explain() บน aggregate function ของฉัน ฉันได้รับตัวชี้สำคัญต่อไปนี้ที่แจ้งว่าการค้นหาของฉันช้า โปรดแก้ไขฉันหากฉันผิด

  1. "indexFilterSet": false
  2. "winningPlan": { "stage": "COLLSCAN", "direction": "forward" },

ดำเนินการค้นหาในบันทึก 9,264,947 และเวลาที่ใช้คือประมาณ 32 seconds ฉันได้ลองใช้ดัชนีแบบผสมและดัชนีฟิลด์เดี่ยวแล้ว แต่ก็ไม่ได้ช่วยอะไรเลย เนื่องจากฉันรู้สึกว่าดัชนีไม่ได้ใช้โดยที่ $match ว่างเปล่า {}

ด้านล่างนี้คือข้อความค้นหาที่ฉันเรียกใช้บน mongoDB โดยใช้ไดรเวอร์ mongoose

Model.aggregate([
  {"$match" : query},
  { $group : {_id: {country: "$Country", exporter: "$Exporter"}, id: {$first: "$_id"}, product: { $first: "$Description" }}},
  { $group : {_id: "$_id.country", data: {$push: { id: "$id", company: "$_id.exporter", product: "$product" }}, count:{$sum:1}}},
  { "$sort": { "count": -1 } },
  { 
    $project: { 
      "data": { "$slice": [ "$data", 3 ] },
      "_id": 1,
      "count": 1
    }
  },
]).allowDiskUse(true).explain()

โดยที่ ข้อความค้นหา ถูกสร้างขึ้นแบบไดนามิก และโดยค่าเริ่มต้นจะว่างเปล่า {} สำหรับการค้นหาทั่วทั้งคอลเลกชัน ฟิลด์ที่มีการจัดทำดัชนีคือ

  1. ดัชนีผสม: {Country: 1, Exporter: 1}

  2. ดัชนีข้อความ: {Description: "text"}

คำตอบอธิบาย () แบบเต็ม:

{
"success": "Successfull",
"status": 200,
"data": {
    "stages": [
        {
            "$cursor": {
                "query": {},
                "fields": {
                    "Country": 1,
                    "Description": 1,
                    "Exporter": 1,
                    "_id": 1
                },
                "queryPlanner": {
                    "plannerVersion": 1,
                    "namespace": "db.OpenExportData",
                    "indexFilterSet": false,
                    "parsedQuery": {},
                    "winningPlan": {
                        "stage": "COLLSCAN",
                        "direction": "forward"
                    },
                    "rejectedPlans": []
                }
            }
        },
        {
            "$group": {
                "_id": {
                    "country": "$Country",
                    "exporter": "$Exporter"
                },
                "id": {
                    "$first": "$_id"
                },
                "product": {
                    "$first": "$Description"
                }
            }
        },
        {
            "$group": {
                "_id": "$_id.country",
                "data": {
                    "$push": {
                        "id": "$id",
                        "company": "$_id.exporter",
                        "product": "$product"
                    }
                },
                "count": {
                    "$sum": {
                        "$const": 1
                    }
                }
            }
        },
        {
            "$sort": {
                "sortKey": {
                    "count": -1
                }
            }
        },
        {
            "$project": {
                "_id": true,
                "count": true,
                "data": {
                    "$slice": [
                        "$data",
                        {
                            "$const": 3
                        }
                    ]
                }
            }
        }
    ],
    "ok": 1
}
}

ขนาดคอลเลกชัน : 9,264,947 บันทึก & 10.2 GB

เวลาตอบสนอง : 32154 ms

ข้อความค้นหาเริ่มช้าลงเนื่องจากขนาดคอลเลกชันของฉันเพิ่มขึ้น


person Abhay Verma    schedule 10.01.2019    source แหล่งที่มา


คำตอบ (2)


หาก ข้อความค้นหา ของคุณคือ {} กลไก mongo จะข้ามขั้นตอน $match และไปที่ $group จะไม่มีการใช้ดัชนี คุณสามารถตรวจสอบด้านบนได้จากผลลัพธ์ explain() ตัวดำเนินการไปป์ไลน์ $match และ $sort สามารถใช้ประโยชน์จากดัชนีได้เมื่อเกิดขึ้นที่จุดเริ่มต้นของไปป์ไลน์ เมื่อดูไปป์ไลน์ของคุณ คุณจะจัดกลุ่มโดยใช้ ประเทศ และ ผู้ส่งออก สิ่งที่คุณสามารถทำได้คือสร้างดัชนีบน {Country: 1, Exporter: 1} และใช้ $sort บน {Country: 1, Exporter: 1} เป็นขั้นตอนแรกของไปป์ไลน์ สิ่งนี้จะทำให้ $group มีประสิทธิภาพมากขึ้น

person simagix    schedule 13.01.2019
comment
ใช่ มันสมเหตุสมผลแล้ว แต่การเรียงลำดับไม่ได้ช่วยอะไรที่ฉันจัดทำดัชนีประเทศและผู้ส่งออก ปรากฎว่านี่เป็นสิ่งที่หลีกเลี่ยงไม่ได้ในขณะนี้ และเราจะไม่นำเสนอคุณลักษณะนี้แก่ผู้ใช้ปลายทาง ซึ่งพวกเขาสามารถดูสรุปบันทึกโดยรวมได้ เนื่องจากจะเป็นคอลเล็กชันขนาดใหญ่ ขอบคุณสำหรับข้อมูลทุกคน! ไชโย! - person Abhay Verma; 22.01.2019

การใช้การรวมเช่นนี้หมายความว่า mongodb ต้องผ่านบันทึกทั้งหมด จากนั้นจัดกลุ่มข้อมูล (โหลด 10 Gb) จากนั้นแบ่งอาร์เรย์ที่จะสร้าง

ยิ่งคอลเลกชันของคุณเติบโตมากเท่าไรก็ยิ่งนานขึ้นเท่านั้น


ฉันคิดว่าแทนที่จะเพิ่มประสิทธิภาพคำขอจริงของคุณ คุณควรพิจารณาแนวทางของคุณอีกครั้ง


ก่อนอื่นฉันจะ find ทุกชื่อ ประเทศ โดยใช้คำขอเดียว จากนั้นใช้คำขอเดียวสำหรับแต่ละประเทศที่ได้รับผู้ส่งออก 3 คนแรก

การใช้ดัชนีใน ประเทศ และใน ผู้ส่งออก

เป็นคำขอที่มากกว่ามาก แต่คำขอมีขนาดเล็กกว่าซึ่งไม่จำเป็นต้องโหลดข้อมูลทั้งหมด ด้วยการเข้าถึงข้อมูลโดยตรงโดยใช้ดัชนีที่เหมาะสม

และเมื่อพิจารณาว่ามีประเทศที่แตกต่างกันไม่มากนัก

person Orelsanpls    schedule 10.01.2019
comment
ข้อกำหนดหลักประการหนึ่งที่นี่คือการค้นหาบทสรุปของผู้ส่งออกที่ไม่ซ้ำกันในแต่ละประเทศ และฉันรู้สึกว่าการบริหารกลุ่มในประเทศและผู้ส่งออกจะเป็นสิ่งจำเป็น โปรดแจ้งให้เราทราบหากมีวิธีอื่นในการดำเนินการดังกล่าว ขอบคุณ! - person Abhay Verma; 10.01.2019
comment
เป็นวิธีการใช้ดัชนีที่กำหนดในฟิลด์เหล่านี้โดยมีการรวม group หรือไม่ - person Abhay Verma; 10.01.2019