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

Bu sayfada, verimli bir sorgu deneyimi oluşturmak için birden fazla alanda aralık ve eşitsizlik filtreleri içeren sorgularda kullanabileceğiniz dizine ekleme stratejisi örnekleri verilmiştir.

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

Sorguları Query Explain ile optimize etme

Sorgunuzun ve dizinlerinizin optimum düzeyde olup olmadığını belirlemek için Query Explain'i kullanarak sorgu planı özetini ve sorgunun yürütme istatistiklerini alabilirsiniz:

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ının kullanılmasının Cloud Firestore tarafından taranan dizin girişi sayısını nasıl azalttığı gösterilmektedir.

Basit sorgular

Çalışanlar koleksiyonuyla ilgili önceki örnekte, (experience ASC, salary ASC) diziniyle çalışan basit sorgu aşağıdaki gibidir:

Java

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

Sorgu, yalnızca beş doküman döndürmek için 95.000 dizin girişini tarar. Sorgu yüklemi 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 biraz deneyimi olacağını ancak çok azının 100.000'den fazla maaş alacağını çıkarabilirsiniz. Bu analizden yola çıkarak salary kısıtlamasının experience kısıtlamasından daha seçici olduğunu görebilirsiniz. Cloud Firestore tarafından sorguyu yürütmek için kullanılan dizini etkilemek istiyorsanız 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");

Yüklemleri eklemek için orderBy() ifadesini açıkça kullandığınızda Cloud Firestore, sorguyu çalıştırmak için (salary ASC, experience ASC) dizinini kullanır. 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 maliyetlidir.

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

Sırada ne var?