대부분의 직원이 어느 정도 경험을 갖췄지만 급여가 100,000을 초과하는 직원은 거의 없을 것이라는 사실을 분야별 전문 지식에서 추론할 수 있습니다. 이 통계를 바탕으로 salary 제약 조건이 experience 제약 조건보다 더 선택적이라는 것을 알 수 있습니다. Cloud Firestore에서 쿼리를 실행하는 데 사용하는 색인에 영향을 주려면 salary 제약조건을 experience 제약조건보다 먼저 정렬하는 orderBy 절을 지정합니다.
orderBy() 절을 명시적으로 사용하여 조건자를 추가하면 Cloud Firestore는 (salary ASC, experience ASC) 색인을 사용하여 쿼리를 실행합니다.
이 쿼리의 첫 번째 범위 필터의 선택성이 이전 쿼리보다 높으므로 쿼리가 더 빠르게 실행되며 비용 효율적입니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-05(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)."]]