Otimizar consultas com filtros de intervalo e desigualdade em várias propriedades
Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
Esta página fornece exemplos de estratégias de indexação que podem ser usadas para consultas
com filtros de intervalo e desigualdade em vários campos para criar uma experiência de consulta
eficiente.
Para determinar se a consulta e os índices usados são ideais, crie uma consulta
usando o Query Explain e analise o resumo de execução.
Java
...// Build the queryQuery<Entity>query=Query.newEntityQueryBuilder().setKind("employees").setFilter(CompositeFilter.and(PropertyFilter.gt("salary",100000),PropertyFilter.gt("experience",0))).setOrderBy(OrderBy("experience"),OrderBy("salary")).build();// Set the explain options to get back *only* the plan summaryQueryResults<Entity>results=datastore.run(query,ExplainOptions.newBuilder().build());// Get the explain metricsOptional<ExplainMetrics>explainMetrics=results.getExplainMetrics();if(!explainMetrics.isPresent()){thrownewException("No explain metrics returned");}// Get the plan summaryPlanSummaryplanSummary=explainMetrics.get().getPlanSummary();List<Map<String,Object>>indexesUsed=planSummary.getIndexesUsed();System.out.println("----- Indexes Used -----");indexesUsed.forEach(map->map.forEach((s,o)->System.out.println(s+": "+o)));// Get the execution statsif(!explainMetrics.getExecutionStats().isPresent()){thrownewException("No execution stats returned");}ExecutionStatsqueryStats=explainMetrics.getExecutionStats().get();Map<String,Object>debugStats=queryStats.getDebugStats();System.out.println("----- Debug Stats -----");debugStats.forEach((s,o)->System.out.println(s+": "+o));
O exemplo a seguir mostra como o uso da ordem correta do índice economiza o
número de entidades que o Firestore no modo Datastore verifica.
Consultas simples
Com o exemplo anterior de um conjunto de funcionários, a consulta simples
executada com o índice (salary, experience) é a seguinte:
A consulta verifica 95.000 entradas de índice apenas para retornar cinco entidades. Um grande número
de entradas de índice foi lido, mas filtrado porque não atendeu ao
predicado de consulta.
Quando você usa explicitamente a cláusula orderBy() para adicionar os predicados na
ordem anterior, o Firestore no modo Datastore usa o índice (salary, experience)
para executar a consulta. Como a seleção do primeiro filtro de intervalo é
melhor do que a consulta anterior, ela é executada mais rapidamente e é econômica.
[[["Fácil de entender","easyToUnderstand","thumb-up"],["Meu problema foi resolvido","solvedMyProblem","thumb-up"],["Outro","otherUp","thumb-up"]],[["Difícil de entender","hardToUnderstand","thumb-down"],["Informações incorretas ou exemplo de código","incorrectInformationOrSampleCode","thumb-down"],["Não contém as informações/amostras de que eu preciso","missingTheInformationSamplesINeed","thumb-down"],["Problema na tradução","translationIssue","thumb-down"],["Outro","otherDown","thumb-down"]],["Última atualização 2025-09-05 UTC."],[[["\u003cp\u003eThis page demonstrates indexing strategies for optimizing queries that involve range and inequality filters across multiple fields.\u003c/p\u003e\n"],["\u003cp\u003eUsing Query Explain helps determine if a query and its associated indexes are optimized for performance, allowing for a review of the execution summary.\u003c/p\u003e\n"],["\u003cp\u003eProper index ordering, by setting the more selective constraints first, significantly reduces the number of scanned entries and improves query efficiency and cost-effectiveness.\u003c/p\u003e\n"],["\u003cp\u003eThe provided examples illustrate how a simple query can scan thousands of index entries only to filter them out, whereas optimized indexing reduces the number of index entries scanned to find the matching documents.\u003c/p\u003e\n"]]],[],null,["# Optimize queries with range and inequality filters on multiple properties\n\nThis page provides examples of indexing strategies 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\nqueries, read about [range and inequality filters on multiple properties](/datastore/docs/multiple-range-fields) concepts .\n\nOptimize queries with Query Explain\n-----------------------------------\n\nTo determine if the query and indexes used are optimal, you can create a query\nusing [Query Explain](/datastore/docs/query-explain-analyze) and review the execution summary. \n\n### Java\n\n ...\n // Build the query\n Query\u003cEntity\u003e query =\n Query.newEntityQueryBuilder()\n .setKind(\"employees\")\n .setFilter(\n CompositeFilter.and(\n PropertyFilter.gt(\"salary\", 100000), PropertyFilter.gt(\"experience\", 0)))\n .setOrderBy(OrderBy(\"experience\"), OrderBy(\"salary\"))\n .build();\n\n // Set the explain options to get back *only* the plan summary\n QueryResults\u003cEntity\u003e results = datastore.run(query, ExplainOptions.newBuilder().build());\n\n // Get the explain metrics\n Optional\u003cExplainMetrics\u003e explainMetrics = results.getExplainMetrics();\n if (!explainMetrics.isPresent()) {\n throw new Exception(\"No explain metrics returned\");\n }\n\n // Get the plan summary\n PlanSummary planSummary = explainMetrics.get().getPlanSummary();\n List\u003cMap\u003cString, Object\u003e\u003e indexesUsed = planSummary.getIndexesUsed();\n System.out.println(\"----- Indexes Used -----\");\n indexesUsed.forEach(map -\u003e map.forEach((s, o) -\u003e System.out.println(s + \": \" + o)));\n\n // Get the execution stats\n if (!explainMetrics.getExecutionStats().isPresent()) {\n throw new Exception(\"No execution stats returned\");\n }\n\n ExecutionStats queryStats = explainMetrics.getExecutionStats().get();\n Map\u003cString, Object\u003e debugStats = queryStats.getDebugStats();\n System.out.println(\"----- Debug Stats -----\");\n debugStats.forEach((s, o) -\u003e System.out.println(s + \": \" + o));\n\nThe following example shows how the use of correct index ordering saves the\nnumber of entities that Firestore in Datastore mode scans.\n\n### Simple queries\n\nWith the [earlier example](/datastore/docs/multiple-range-fields#indexing_considerations) of a collection of employees, the simple query\nthat runs with the `(salary, experience)` index is as follows: \n\n### GQL\n\n SELECT *\n FROM /employees\n WHERE salary \u003e 100000 AND experience \u003e 0\n ORDER BY experience, salary;\n\n### Java\n\n Query\u003cEntity\u003e query =\n Query.newEntityQueryBuilder()\n .setKind(\"employees\")\n .setFilter(\n CompositeFilter.and(\n PropertyFilter.gt(\"salary\", 100000), PropertyFilter.gt(\"experience\", 0)))\n .setOrderBy(OrderBy(\"experience\"), OrderBy(\"salary\"))\n .build();\n\nThe query scans 95000 index entries only to return 5 entities. A large number\nof index entries were read but filtered out because they did not satisfy the\nquery predicate. \n\n```scilab\n// Output query planning info\n{\n \"indexesUsed\": [\n {\n \"query_scope\": \"Collection Group\",\n \"properties\": \"(experience ASC, salary ASC, __name__ ASC)\"\n }\n ]\n },\n // Output Query Execution Stats\n {\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\nAs per the earlier example, we can infer that the `salary` constraint is more\nselective than the `experience` constraint. \n\n### GQL\n\n SELECT *\n FROM /employees\n WHERE salary \u003e 100000 AND experience \u003e 0\n ORDER BY salary, experience;\n\n### Java\n\n Query\u003cEntity\u003e query =\n Query.newEntityQueryBuilder()\n .setKind(\"employees\")\n .setFilter(\n CompositeFilter.and(\n PropertyFilter.gt(\"salary\", 100000), PropertyFilter.gt(\"experience\", 0)))\n .setOrderBy(OrderBy(\"salary\"), OrderBy(\"experience\"))\n .build();\n\nWhen you explicitly use the `orderBy()` clause to add the predicates in the\nearlier order, Firestore in Datastore mode uses the `(salary, experience)` index\nto run the query. Since the selection of the first range filter is\nbetter than the earlier query, the query runs faster and is cost-efficient. \n\n```scilab\n // Output query planning info\n{\n \"indexesUsed\": [\n {\n \"query_scope\": \"Collection Group\",\n \"properties\": \"(salary ASC, experience ASC, __name__ ASC)\"\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\n- Learn about [Query Explain](/datastore/docs/query-explain-analyze)."]]