Tối ưu hoá truy vấn bằng bộ lọc phạm vi và bất đẳng thức trên nhiều trường

Trang này cung cấp các ví dụ về chiến lược lập chỉ mục mà bạn có thể sử dụng cho các truy vấn có bộ lọc phạm vi và bộ lọc bất đẳng thức trên nhiều trường để tạo trải nghiệm truy vấn hiệu quả.

Trước khi bạn tối ưu hoá truy vấn của mình, hãy đọc về các khái niệm có liên quan.

Tối ưu hoá truy vấn bằng tính năng Giải thích truy vấn

Để xác định xem truy vấn và chỉ mục của bạn có tối ưu hay không, bạn có thể sử dụng tính năng Giải thích truy vấn để nhận bản tóm tắt kế hoạch truy vấn và số liệu thống kê về việc thực thi của truy vấn:

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

Ví dụ sau đây cho thấy cách sử dụng thứ tự chỉ mục chính xác làm giảm số lượng mục nhập chỉ mục mà Cloud Firestore quét.

Truy vấn đơn giản

Với ví dụ trước về một tập hợp nhân viên, truy vấn đơn giản chạy bằng chỉ mục (experience ASC, salary ASC) như sau:

Java

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

Truy vấn chỉ quét 95.000 mục nhập trong chỉ mục để trả về năm tài liệu. Vì không đáp ứng được mệnh đề truy vấn, nên một lượng lớn mục nhập chỉ mục được đọc nhưng bị lọc ra.

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

Bạn có thể suy luận từ chuyên môn trong lĩnh vực này rằng hầu hết nhân viên sẽ có ít nhất một chút kinh nghiệm, nhưng ít người có mức lương hơn 100.000. Với thông tin chi tiết này, bạn có thể thấy rằng quy tắc ràng buộc salary có tính lựa chọn cao hơn so với quy tắc ràng buộc experience. Để ảnh hưởng đến chỉ mục mà Cloud Firestore sử dụng để thực thi truy vấn, hãy chỉ định mệnh đề orderBy sắp xếp quy tắc ràng buộc salary trước quy tắc ràng buộc experience.

Java

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

Khi bạn sử dụng mệnh đề orderBy() một cách rõ ràng để thêm các mệnh đề, Cloud Firestore sẽ sử dụng chỉ mục (salary ASC, experience ASC) để chạy truy vấn. Vì độ chọn lọc của bộ lọc dải ô đầu tiên cao hơn trong truy vấn này so với truy vấn trước, nên truy vấn này chạy nhanh hơn và tiết kiệm chi phí hơn.

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

Bước tiếp theo