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 sorgular için kullanabileceğiniz dizine ekleme stratejisi örnekleri verilmiştir.

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

Sorgu açıklama özelliğiyle sorguları optimize etme

Sorgunuzun ve dizinlerinizin optimal olup olmadığını belirlemek için Sorgu Açıkla'yı 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'ün taradığı dizin girişlerinin sayısını nasıl azalttığı gösterilmektedir.

Basit sorgular

Çalışan koleksiyonunun önceki örneğinde, (experience ASC, salary ASC) dizini ile çalıştırılan 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 önerme 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ığından, çoğu çalışanın en azından biraz deneyime sahip olacağını ancak çok azının 100.000'den fazla maaş alacağını anlayabilirsiniz. Bu analize göre, salary kısıtlamasının experience kısıtlamasından daha seçici olduğunu görebilirsiniz. Cloud Firestore'nin 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 yan tümcesi belirtin.

Java

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

Önerme eklemek için orderBy() yan tümcesini açıkça kullandığınızda Cloud Firestore, sorguyu çalıştırmak için (salary ASC, experience ASC) dizini kullanır. Bu sorgudaki 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?