Aralık ve eşitsizlik filtreleriyle birden fazla alanda sorguları optimize etme

Bu sayfada, etkili bir sorgu deneyimi oluşturmak için birden fazla alanda aralık ve eşitsizlik filtrelerine sahip sorgularda kullanılması gereken dizine ekleme stratejisiyle ilgili örnekler sunulmaktadır.

Sorgularınızı optimize etmeden önce ilgili kavramlar hakkında bilgi edinin.

Sorgu Açıklaması ile sorguları optimize etme

Kullanılan sorgu ve dizinlerin optimum durumda olup olmadığını belirlemek için sorgunun sorgu planı özetini ve yürütme istatistiklerini almak üzere Sorgu Açıklaması'nı kullanabilirsiniz:

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);

Aşağıdaki örnekte, doğru dizin sıralaması kullanmanın Cloud Firestore'un taradığı dizin girişi sayısını nasıl azalttığı gösterilmektedir.

Basit sorgular

Çalışanlardan oluşan bir koleksiyonun önceki örneğine göre (experience ASC, salary ASC) diziniyle çalışan basit sorgu şu şekildedir:

Java

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

Sorgu, 95.000 dizin girişini yalnızca 5 doküman döndürmek için tarar. Sorgu koşulu karşılanmadığından, çok sayıda dizin girişi okunur ancak filtrelenir.

// 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"
        }
    }
}

Alan uzmanlığından, çoğu çalışanın en azından bir miktar deneyime sahip olduğu, ancak çok az kişinin 100.000'in üzerinde maaşa sahip olacağı sonucunu çıkarabiliriz. Bu bilgiden yola çıkarak, salary kısıtlamasının experience kısıtlamasına göre daha seçici olduğu sonucuna varabiliriz. Cloud Firestore'un sorguyu yürütmek için kullandığı dizini etkilemek amacıyla salary kısıtlamasını experience kısıtlamasından önce sıralayan bir orderBy ifadesi belirtin.

Java

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

Koşulları eklemek için açıkça orderBy() ifadesini kullandığınızda Cloud Firestore, sorguyu çalıştırmak için (salary ASC, experience ASC) dizinini kullanır. Dolayısıyla, bu sorguda ilk aralık filtresinin seçiciliği önceki sorguya kıyasla daha yüksek olduğundan sorgu daha hızlı çalışır ve daha uygun maliyetli olur.

// 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"
        }
    }
}

Sonraki Adımlar