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 verilmektedir.

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

Sorgu Açıklama ile sorguları optimize etme

Sorgunuzun ve dizinlerinizin optimum olup olmadığını belirlemek için Query Explain'i kullanarak sorgunun sorgu planı özetini ve 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şlerinin sayısını nasıl azalttığı gösterilmektedir.

Basit sorgular

Çalışan 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 tarıyor. Sorgu koşulu karşılanmadığı için ç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ığına dayanarak çoğu çalışanın en azından biraz deneyimi olacağını ancak çok azının 100.000'den fazla maaş alacağını tahmin edebilirsiniz. Bu analizden yola çıkarak salary sınırlamasının experience sınırlamasından daha seçici olduğunu görebilirsiniz. Cloud Firestore sorguyu yürütmek için kullandığı dizini etkilemek üzere 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?