Optimiza las consultas con filtros de rango y desigualdad en varias propiedades
Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
En esta página, se proporcionan ejemplos de estrategias de indexación que puedes usar para las consultas con rangos y filtros de desigualdad en varios campos para crear una experiencia de consulta eficiente.
Para determinar si la consulta y los índices usados son óptimos, puedes crear una consulta con la Explicación de consulta y revisar el resumen de ejecución.
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));
En el siguiente ejemplo, se muestra cómo el uso del orden correcto de índices ahorra la
cantidad de entidades que analiza Firestore en modo Datastore.
Consultas simples
Con el ejemplo anterior de una colección de empleados, la consulta simple
que se ejecuta con el índice (salary, experience) es de la siguiente manera:
La consulta analiza 95,000 entradas de índice solo para mostrar 5 entidades. Se leyó una gran cantidad de entradas de índice, pero se filtraron porque no satisfacían el predicado de la consulta.
Cuando usas la cláusula orderBy() de forma explícita para agregar los predicados en el
orden anterior, Firestore en modo Datastore usa el índice (salary, experience)
para ejecutar la consulta. Dado que la selección del primer filtro de rango es
mejor que la consulta anterior, la consulta se ejecuta más rápido y es rentable.
[[["Fácil de comprender","easyToUnderstand","thumb-up"],["Resolvió mi problema","solvedMyProblem","thumb-up"],["Otro","otherUp","thumb-up"]],[["Difícil de entender","hardToUnderstand","thumb-down"],["Información o código de muestra incorrectos","incorrectInformationOrSampleCode","thumb-down"],["Faltan la información o los ejemplos que necesito","missingTheInformationSamplesINeed","thumb-down"],["Problema de traducción","translationIssue","thumb-down"],["Otro","otherDown","thumb-down"]],["Última actualización: 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)."]]