تحسين طلبات البحث باستخدام فلاتر النطاق وعدم المساواة في حقول متعدّدة

تقدّم هذه الصفحة أمثلة على استراتيجية الفهرسة التي يجب استخدامها لطلبات البحث التي تتضمّن فلاتر للنطاق وعدم المساواة في عدة حقول لإنشاء تجربة طلب بحث فعّالة.

يُرجى الاطّلاع على المفاهيم ذات الصلة قبل تحسين طلبات البحث.

تحسين طلبات البحث باستخدام "شرح طلب البحث"

ولتحديد ما إذا كان طلب البحث والفهارس المستخدمة مثاليًا، يمكنك استخدام شرح طلب البحث للحصول على ملخّص خطة طلب البحث وإحصاءات التنفيذ لطلب البحث:

Java

Query q = db.collection("employees").whereGreaterThan("salary",
100000).whereGreaterThan("experience", 0);

ExplainResults<QuerySnapshot> explainResults = q.explain(ExplainOptions.builder().analyze(true).build()).get();
ExplainMetrics metrics = explainResults.getMetrics();

PlanSummary planSummary = metrics.getPlanSummary();
ExecutionStats executionStats = metrics.getExecutionStats();

System.out.println(planSummary.getIndexesUsed());
System.out.println(stats.getResultsReturned());
System.out.println(stats.getExecutionDuration());
System.out.println(stats.getReadOperations());
System.out.println(stats.getDebugStats());

Node.js

let q = db.collection("employees")
      .where("salary", ">", 100000)
      .where("experience", ">",0);

let options = { analyze : 'true' };
let explainResults = await q.explain(options);

let planSummary = explainResults.metrics.planSummary;
let stats = explainResults.metrics.executionStats;

console.log(planSummary);
console.log(stats);

يوضّح المثال التالي كيف يؤدي استخدام ترتيب الفهرس الصحيح إلى تقليل عدد إدخالات الفهرس التي تفحصها Cloud Firestore.

طلبات بحث بسيطة

باستخدام المثال السابق لمجموعة من الموظفين، يكون الاستعلام البسيط الذي يتم تشغيله باستخدام فهرس (experience ASC, salary ASC) على النحو التالي:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("experience")
  .orderBy("salary");

يفحص الاستعلام 95000 إدخال فهرس فقط لعرض 5 مستندات فقط. نظرًا لعدم استيفاء إسناد طلب البحث، تتم قراءة عدد كبير من إدخالات الفهرس، ولكن تتم تصفيتها.

// Output query planning info
{
    "indexesUsed": [
        {
            "properties": "(experience ASC, salary ASC, __name__ ASC)",
            "query_scope": "Collection"
        }
    ],

    // Output Query Execution Stats
    "resultsReturned": "5",
    "executionDuration": "2.5s",
    "readOperations": "100",
    "debugStats": {
        "index_entries_scanned": "95000",
        "documents_scanned": "5",
        "billing_details": {
            "documents_billable": "5",
            "index_entries_billable": "95000",
            "small_ops": "0",
            "min_query_cost": "0"
        }
    }
}

يمكننا أن نستنتج من الخبرة في المجال أن معظم الموظفين سيكون لديهم على الأقل بعض الخبرة لكن القليل منهم سيكون لديهم راتب أكثر من 100000. استنادًا إلى هذه الإحصاءات، يمكننا أن نستنتج أنّ القيد salary أكثر انتقائية من القيد experience. للتأثير في الفهرس الذي تستخدمه Cloud Firestore لتنفيذ طلب البحث، حدِّد عبارة orderBy تطلب القيد salary قبل القيد experience.

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("salary")
  .orderBy("experience");

عند استخدام عبارة orderBy() بشكل صريح لإضافة العلامات، تستخدم Cloud Firestore فهرس (salary ASC, experience ASC) لتنفيذ طلب البحث. وبالتالي، نظرًا لأن انتقائية فلتر النطاق الأول أعلى في طلب البحث هذا مقارنةً بالاستعلام السابق، يعمل الاستعلام بشكل أسرع وأكثر فعالية من حيث التكلفة.

// Output query planning info
{
    "indexesUsed": [
        {
            "properties": "(salary ASC, experience ASC, __name__ ASC)",
            "query_scope": "Collection"
        }
    ],

    // Output Query Execution Stats
    "resultsReturned": "5",
    "executionDuration": "0.2s",
    "readOperations": "6",
    "debugStats": {
        "index_entries_scanned": "1000",
        "documents_scanned": "5",
        "billing_details": {
            "documents_billable": "5",
            "index_entries_billable": "1000",
            "small_ops": "0",
            "min_query_cost": "0"
        }
    }
}

ما هي الخطوات التالية؟