Auf dieser Seite finden Sie Beispiele für Indexierungsstrategien, die Sie für Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder verwenden können, um eine effiziente Abfrage zu ermöglichen.
Bevor Sie Ihre Abfragen optimieren, sollten Sie sich mit den Konzepten für Bereichs- und Ungleichheitsfilter für mehrere Attribute vertraut machen .
Abfragen mit Query Explain optimieren
Um festzustellen, ob die verwendete Abfrage und die verwendeten Indexe optimal sind, können Sie mit Query Explain eine Abfrage erstellen und die Zusammenfassung der Ausführung prüfen.
Java
...
// Build the query
Query<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 summary
QueryResults<Entity> results = datastore.run(query, ExplainOptions.newBuilder().build());
// Get the explain metrics
Optional<ExplainMetrics> explainMetrics = results.getExplainMetrics();
if (!explainMetrics.isPresent()) {
throw new Exception("No explain metrics returned");
}
// Get the plan summary
PlanSummary planSummary = 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 stats
if (!explainMetrics.getExecutionStats().isPresent()) {
throw new Exception("No execution stats returned");
}
ExecutionStats queryStats = explainMetrics.getExecutionStats().get();
Map<String, Object> debugStats = queryStats.getDebugStats();
System.out.println("----- Debug Stats -----");
debugStats.forEach((s, o) -> System.out.println(s + ": " + o));
Im folgenden Beispiel wird gezeigt, wie durch die Verwendung der richtigen Indexreihenfolge die Anzahl der Entitäten reduziert wird, die von Firestore im Datastore-Modus gescannt werden.
Einfache Abfragen
Im vorherigen Beispiel für eine Sammlung von Mitarbeitern sieht die einfache Abfrage, die mit dem (salary, experience)-Index ausgeführt wird, so aus:
GQL
SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY experience, salary;
Java
Query<Entity> query =
Query.newEntityQueryBuilder()
.setKind("employees")
.setFilter(
CompositeFilter.and(
PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
.setOrderBy(OrderBy("experience"), OrderBy("salary"))
.build();
Bei der Abfrage werden 95.000 Indexeinträge gescannt, um nur 5 Entitäten zurückzugeben. Eine große Anzahl von Indexeinträgen wurde gelesen, aber herausgefiltert, weil sie das Abfrageprädikat nicht erfüllt haben.
// Output query planning info { "indexesUsed": [ { "query_scope": "Collection Group", "properties": "(experience ASC, salary ASC, __name__ ASC)" } ] }, // 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" } } }
Wie im vorherigen Beispiel zu sehen ist, ist die Einschränkung salary selektiver als die Einschränkung experience.
GQL
SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY salary, experience;
Java
Query<Entity> query =
Query.newEntityQueryBuilder()
.setKind("employees")
.setFilter(
CompositeFilter.and(
PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
.setOrderBy(OrderBy("salary"), OrderBy("experience"))
.build();
Wenn Sie die orderBy()-Klausel explizit verwenden, um die Prädikate in der vorherigen Reihenfolge hinzuzufügen, verwendet Firestore im Datastore-Modus den (salary, experience)-Index, um die Abfrage auszuführen. Da die Auswahl des ersten Bereichsfilters besser ist als bei der vorherigen Abfrage, wird die Abfrage schneller ausgeführt und ist kosteneffizient.
// Output query planning info { "indexesUsed": [ { "query_scope": "Collection Group", "properties": "(salary ASC, experience ASC, __name__ ASC)" } ], // 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" } } }