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
Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
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ả.
Để 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 Query Explain để nhận được 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 truy vấn:
Truy vấn chỉ quét 95.000 mục trong chỉ mục để trả về 5 tài liệu. Vì vị từ truy vấn không được đáp ứng, nên một số lượng lớn các mục nhập chỉ mục được đọc nhưng bị lọc ra.
Bạn có thể suy luận từ kiến thức chuyên môn về lĩnh vực này rằng hầu hết nhân viên sẽ có ít nhất một số kinh nghiệm nhưng ít người có mức lương trên 100.000. Dựa vào thông tin chi tiết này, bạn có thể thấy rằng điều kiện ràng buộc salary có tính chọn lọc hơn điều kiện ràng buộc experience. Để tác động đến chỉ mục mà Cloud Firestore dùng để thực thi truy vấn, hãy chỉ định một 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.
Khi bạn sử dụng mệnh đề orderBy() một cách rõ ràng để thêm các vị từ, 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 chạy nhanh hơn và tiết kiệm chi phí hơn.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-09-06 UTC."],[],[],null,["\u003cbr /\u003e\n\nThis page provides examples of indexing strategy that you can use for queries\nwith range and inequality filters on multiple fields to create an efficient\nquery experience.\n\nBefore you optimize your queries, read about [the related concepts](/docs/firestore/query-data/multiple-range-fields).\n\nOptimize queries with Query Explain\n\nTo determine if your query and indexes are optimal, you can use [Query\nExplain](/docs/firestore/query-explain) to get the query plan summary and execution statistics\nof the query: \n\nJava \n\n Query q = db.collection(\"employees\").whereGreaterThan(\"salary\",\n 100000).whereGreaterThan(\"experience\", 0);\n\n ExplainResults\u003cQuerySnapshot\u003e explainResults = q.explain(ExplainOptions.builder().analyze(true).build()).get();\n ExplainMetrics metrics = explainResults.getMetrics();\n\n PlanSummary planSummary = metrics.getPlanSummary();\n ExecutionStats executionStats = metrics.getExecutionStats();\n\n System.out.println(planSummary.getIndexesUsed());\n System.out.println(stats.getResultsReturned());\n System.out.println(stats.getExecutionDuration());\n System.out.println(stats.getReadOperations());\n System.out.println(stats.getDebugStats());\n\nNode.js \n\n let q = db.collection(\"employees\")\n .where(\"salary\", \"\u003e\", 100000)\n .where(\"experience\", \"\u003e\",0);\n\n let options = { analyze : 'true' };\n let explainResults = await q.explain(options);\n\n let planSummary = explainResults.metrics.planSummary;\n let stats = explainResults.metrics.executionStats;\n\n console.log(planSummary);\n console.log(stats);\n\nThe following example shows how the use of correct index ordering reduces the\nnumber of index entries that Cloud Firestore scans.\n\nSimple queries\n\nWith the [earlier example](/docs/firestore/query-data/multiple-range-fields#indexing_considerations) of a collection of employees, the simple query\nthat runs with the `(experience ASC, salary ASC)` index is as follows: \n\nJava \n\n db.collection(\"employees\")\n .whereGreaterThan(\"salary\", 100000)\n .whereGreaterThan(\"experience\", 0)\n .orderBy(\"experience\")\n .orderBy(\"salary\");\n\nThe query scans 95000 index entries only to return five documents. Since the query\npredicate isn't satisfied, a large number of index entries are read but are\nfiltered out. \n\n```scilab\n// Output query planning info\n{\n \"indexesUsed\": [\n {\n \"properties\": \"(experience ASC, salary ASC, __name__ ASC)\",\n \"query_scope\": \"Collection\"\n }\n ],\n\n // Output Query Execution Stats\n \"resultsReturned\": \"5\",\n \"executionDuration\": \"2.5s\",\n \"readOperations\": \"100\",\n \"debugStats\": {\n \"index_entries_scanned\": \"95000\",\n \"documents_scanned\": \"5\",\n \"billing_details\": {\n \"documents_billable\": \"5\",\n \"index_entries_billable\": \"95000\",\n \"small_ops\": \"0\",\n \"min_query_cost\": \"0\"\n }\n }\n}\n```\n\nYou can infer from domain expertise that most employees will have at least some\nexperience but few will have a salary that is more than 100000. Given this\ninsight, you can see that the `salary` constraint is more selective than the\n`experience` constraint. To influence the index that Cloud Firestore uses to\nexecute the query, specify an `orderBy` clause that orders the `salary`\nconstraint before the `experience` constraint. \n\nJava \n\n db.collection(\"employees\")\n .whereGreaterThan(\"salary\", 100000)\n .whereGreaterThan(\"experience\", 0)\n .orderBy(\"salary\")\n .orderBy(\"experience\");\n\nWhen you explicitly use the `orderBy()` clause to add the predicates,\nCloud Firestore uses the `(salary ASC, experience ASC)` index to run the query.\nSince the selectivity of the first range filter is higher in this query\ncompared to the earlier query, the query runs faster and is more cost efficient. \n\n```scilab\n// Output query planning info\n{\n \"indexesUsed\": [\n {\n \"properties\": \"(salary ASC, experience ASC, __name__ ASC)\",\n \"query_scope\": \"Collection\"\n }\n ],\n\n // Output Query Execution Stats\n \"resultsReturned\": \"5\",\n \"executionDuration\": \"0.2s\",\n \"readOperations\": \"6\",\n \"debugStats\": {\n \"index_entries_scanned\": \"1000\",\n \"documents_scanned\": \"5\",\n \"billing_details\": {\n \"documents_billable\": \"5\",\n \"index_entries_billable\": \"1000\",\n \"small_ops\": \"0\",\n \"min_query_cost\": \"0\"\n }\n }\n}\n```\n\nWhat's next\n\n- Learn about [Query Explain](/docs/firestore/query-explain).\n- Learn about [indexing best practices](/docs/firestore/query-data/index-overview#indexing_best_practices)."]]