Auf dieser Seite wird die Ausgabe einer mit „Query Explain“ ausgeführten Abfrage erläutert. Informationen zum Ausführen einer Abfrage mit Query Explain finden Sie unter Abfrageausführung mit Query Explain analysieren.
Häufig verwendete Konzepte
Im gesamten Ausführungsbaum werden die folgenden gängigen Konzepte und Begriffe verwendet.
Zeilen und Datensätze
Die Begriffe Zeile und Datensatz werden allgemein für ein Dokument oder einen Indexeintrag verwendet.
Variablen
$
steht für eine Variable, die im Ausführungsbaum erstellt oder auf die verwiesen wird. Beispiel: $foo_1
Diese Variablen werden in der Regel verwendet, um auf den Inhalt eines Dokuments oder den Wert eines Ausdrucks zu verweisen, der während der Ausführung einer Abfrage ausgewertet wird.
Die folgenden internen Variablen können in den Ausführungsknoten vorkommen:
$__key__
: Der Schlüssel ist eine interne Kennung für ein Dokument. Dies ist eine absolute, eindeutige Kennung mit dem Projekt, der Datenbank und dem vollständigen Pfad des Dokuments.$__id__
: Die ID ist eine eindeutige Kennung für ein Dokument in der Sammlung. Sie ist innerhalb einer einzelnen Sammlung eindeutig.
Betrachten Sie ein Beispiel, in dem ein Compute
-Knoten verwendet wird, um die __id__
aus dem Dokument __key__
zu berechnen:
Compute
| $__id__1: _id($__key__)
| records returned: 1
Einschränkungen und Bereiche
Einige Scan-Knoten verwenden die Attribute constraints
und ranges
, um den Bereich der gescannten Werte zu beschreiben. Diese Attribute verwenden ein Bereichsbaumformat, das eine Liste von Werten enthält. Diese Werte entsprechen der sortierten Liste der Schlüssel, die in der Indexdefinition enthalten sind. Der erste Bereich, der im Baum angezeigt wird, hier (1..5]
, entspricht beispielsweise den Einschränkungen für den ersten Schlüssel, hier a
, in der sortierten Liste der Schlüssel:
| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
|----(1..5]
|----[1L]
Jede Einrückungsebene gibt die Einschränkung an, die für den nächsten Schlüssel in der Liste gilt. Eckige Klammern stehen für einen eingeschlossenen Bereich, runde Klammern für einen ausgeschlossenen Bereich. In diesem Fall wird die Einschränkung in 1 < "a" <= 5
und "b" = 1
übersetzt.
Im folgenden Beispiel mit mehreren Zweigen für a
entspricht die Einschränkung 1 < a <= 5 OR a = 10
:
| constraints: /
|----(1L, 5L]
|----[10L]
Schlüsselvariablen
In einigen Scanknoten (z. B. SequentialScan
) gibt es sowohl eine Liste von Schlüsseln als Teil des Attributs index
als auch ein separates Attribut keys
im Knoten Scan
. Das Attribut keys
im Knoten Scan
gibt den Variablennamen jedes Schlüssels in der Indexdefinition in der richtigen Reihenfolge an. Mit den Variablen kann auf die Laufzeitwerte des gescannten Felds weiter oben im Ausführungsbaum verwiesen werden.
Im folgenden Beispiel wird der Wert des Felds user
für das aktuelle Dokument der Variablen $user_1
und der Wert von date_placed
der Variablen $date_placed_1
zugeordnet.
index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]
Ausführungsknoten
Ein Baum für die Ausführung von Abfragen kann die folgenden Knoten enthalten.
SeekingScan
Stellt einen dynamischen Scan dar, bei dem die zurückgegebenen Zeilen möglicherweise nicht in einem einzelnen sequenziellen Bereich des Index liegen und mehrere separate Scans ausgeführt werden müssen, um die Abfrage zu erfüllen.
Bei einer Abfrage, in der a
vorhanden ist und b
gleich 1 ist, die auf einem Index von ["a" ASC, "b" ASC]
basiert, muss beispielsweise für jeden eindeutigen Wert von a
ein separater, möglicherweise nicht sequenzieller Bereich gescannt und zurückgegeben werden.
Das ist effizienter als ein vollständiger TableScan
, aber weniger effizient als ein einzelner SequentialScan
für einen zusammengesetzten Index von ["b" ASC, "a" ASC]
.
• SeekingScan
| constraints: /
|----(-∞..+∞)
|----[1L]
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, quantity ASC, __key__ ASC]
| keys: [user ASC, quantity ASC, __key__ ASC]
| properties: Selection { user }
| records returned: 1
| records scanned: 1
SequentialScan
Stellt einen Scan eines statischen, sequenziellen Bereichs von Zeilen im Speicher dar, der in einem einzelnen Lesevorgang ausgeführt werden kann.
key ordering length
bezieht sich auf die Anzahl der Schlüssel, die beibehalten und in der ursprünglichen Schlüsselreihenfolge zurückgegeben werden müssen. Bei einem Schema von [k1, k2, k3]
bedeutet eine Schlüsselreihenfolgenlänge von 0, dass der Scan in beliebiger Reihenfolge zurückgegeben werden kann. Bei 1 wird nach k1 sortiert, aber Zeilen mit demselben k1-Wert können in beliebiger Reihenfolge zurückgegeben werden. Bei 3 werden Dokumente in genau sortierter Reihenfolge zurückgegeben.
• SequentialScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| key ordering length: 3
| keys: [user ASC, date_placed ASC, __key__ ASC]
| limit: 10
| properties: Selection { a }
| ranges: /
| records returned: 1
| records scanned: 1
UniqueScan
Stellt einen Scan eines statischen, sequenziellen Zeilenbereichs im Speicher mit In-Memory-Deduplizierung von Zeilen dar.
• UniqueScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| keys: [user ASC, date_placed ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
|----(-∞..+∞)
| records returned: 1
| records scanned: 1
TableAccess
Führt die ID der angegebenen Zeile mit dem tatsächlichen Zeileninhalt aus dem primären Speicher zusammen. TableAccess
ist erforderlich, wenn für einen übergeordneten Knoten (oder das endgültige Abfrageergebnis) eine Teilmenge von Feldern aus den Dokumenten erforderlich ist.
• TableAccess
| order: PRESERVE_INPUT_ORDER
| peak memory usage: 4.00 KiB (4,096 B)
| properties: *
| records returned: 1
LookupById
Führt einen Join aus, indem Dokumente in einer fremden Sammlung anhand ihrer ID gesucht werden. Die nachzuschlagenden IDs stammen aus einem Feld in den Eingabedokumenten. Die Ergebnisse der Suche werden den Eingabedokumenten als neues Feld hinzugefügt.
• LookupById
| local_field: $localField_1
| foreign_datasource: (default)#/**/foreign
| output: $output_1
TableScan
Ein vollständiger, ungeordneter Scan einer Sammlung. Wird verwendet, wenn eine Abfrage ohne zugehörigen Index ausgeführt wird.
Die Reihenfolge kann entweder STABLE
oder UNDEFINED
sein. STABLE
steht für eine deterministische Reihenfolge.
• TableScan
| order: STABLE
| properties: *
| records returned: 1
| records scanned: 1
| source: (default)#/**/collection
HashAggregate
Hashbasierte Implementierung von Aggregatvorgängen. Erfordert die Materialisierung der gesamten Gruppe im Arbeitsspeicher, bevor das Ergebnis zurückgegeben wird, und darf das Speicherlimit für Abfragen nicht überschreiten.
• HashAggregate
| aggregations: [sum($b_1) AS total]
| groups: [$a_1]
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 0
StreamAggregate
Spezialisierter Aggregatknoten, der jeweils nur den Status für eine einzelne Gruppe verwaltet, wodurch die maximale Arbeitsspeichernutzung reduziert wird. Wird verwendet, wenn der zugrunde liegende untergeordnete Knoten Gruppen sequenziell zurückgibt. Das ist beispielsweise der Fall, wenn Sie nach eindeutigen Werten eines Felds gruppieren und gleichzeitig einen Index für dieses Feld verwenden.
• StreamAggregate
| keys: [foo ASC, bar ASC]
| properties: Selection { baz }
| aggregations: [$sum($foo_1) AS baz]
MajorSort
Führt einen Sortiervorgang für eine feste Gruppe von Attributen aus. Alle Datensätze werden gleichzeitig im Arbeitsspeicher materialisiert und die sortierten Werte werden in der richtigen Reihenfolge zurückgegeben. Die Größe des Sortiersatzes ist durch das Limit für den Abfragespeicher begrenzt.
Wenn ein nachfolgendes Limit angegeben wird, wird ein Top-k-Sortieralgorithmus verwendet, um die Speichernutzung zu reduzieren. Damit können Sortierungen für eine beliebig große Menge von Datensätzen durchgeführt werden, solange der zum Speichern der k berücksichtigten Elemente verwendete Arbeitsspeicher das Limit nicht überschreitet.
• MajorSort
| fields: [a ASC, b DESC]
| limit: 10
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 1
Concat
Verkettet die Ergebnisse mehrerer untergeordneter Knoten und gibt das Ergebnis an den übergeordneten Knoten zurück. Bei diesem Knoten werden Ergebnisse, die in mehreren untergeordneten Elementen vorkommen, nicht dedupliziert und die Reihenfolge der zurückgegebenen Ergebnisse ist nicht deterministisch.
• Concat
├── • TableAccess
...
├── • TableAccess
Compute
Wertet eine Reihe von Ausdrücken aus und weist die Ergebnisse einer Reihe von Variablen zu.
• Compute
| $user_1: user
| $full_name_1: str_concat($first_name_1, " ", $last_name_1)
| $address_1: UNSET
| records returned: 1
Filter
Gibt Zeilen nur dann zurück, wenn sie mit dem angegebenen Ausdruck übereinstimmen.
• Filter
| expression: $eq(foo, "bar")
| records returned: 1
Werte
Erstellt eine Folge von Literalwerten, mit denen gearbeitet werden kann. Wird hauptsächlich verwendet, wenn eine Liste von Dokumenten als Eingabe für eine Abfrage bereitgestellt wird.
• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]
Unnest
Hebt die Verschachtelung des vom untergeordneten Knoten erstellten Werts auf.
• Unnest
| expression: foo AS unnested_foo
Limit
Beschränkt die Anzahl der an den übergeordneten Knoten zurückgegebenen Zeilen.
• Limit
| limit: 10
| records returned: 1
Offset
Überspringt eine festgelegte Anzahl von Zeilen, die vom untergeordneten Knoten generiert werden.
• Offset
| offset: 10
| records returned: 1