Ta strona wyjaśnia, jakie dane wyjściowe generuje zapytanie wykonane za pomocą funkcji Query Explain. Aby dowiedzieć się, jak wykonać zapytanie za pomocą funkcji Query Explain, przeczytaj artykuł Analizowanie wykonywania zapytań za pomocą funkcji Query Explain.
Typowe pojęcia
W drzewie wykonania używane są te typowe pojęcia i terminy.
Wiersze i rekordy
Terminy wiersz i rekord są używane ogólnie w odniesieniu do dokumentu lub wpisu w indeksie.
Zmienne
$ oznacza zmienną, która jest tworzona lub
do której odwołuje się drzewo wykonania. Na przykład: $foo_1. Te zmienne są zwykle używane do
odwoływania się do zawartości dokumentu lub wartości wyrażenia obliczonego
podczas wykonywania zapytania.
W węzłach wykonania mogą pojawić się te zmienne wewnętrzne:
$__key__– klucz jest wewnętrznym identyfikatorem dokumentu. Jest to bezwzględny, unikalny identyfikator zawierający projekt, bazę danych i pełną ścieżkę dokumentu.$__id__– identyfikator jest unikalnym identyfikatorem dokumentu w obrębie kolekcji. Jest on unikalny w obrębie jednej kolekcji.$rid– identyfikator wiersza jest wewnętrznym identyfikatorem dokumentu w pamięci. Jest on unikalny w obrębie jednej kolekcji.
Rozważmy przykład, w którym węzeł Compute służy do obliczania wartości __id__ na podstawie dokumentu __key__:
Compute
| $__id__1: _id($__key__)
| records returned: 1
Ograniczenia i zakresy
Niektóre węzły skanowania używają atrybutów constraints i ranges do opisywania zakresu skanowanych wartości. Te atrybuty używają formatu drzewa zakresów, który zawiera listę wartości. Te wartości odpowiadają uporządkowanej liście kluczy, które pojawiają się w definicji indeksu. Na przykład pierwszy zakres, który pojawia się
w drzewie, w tym przypadku (1..5], odpowiada ograniczeniom dotyczącym pierwszego klucza,
w tym przypadku a, na uporządkowanej liście kluczy:
| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
|----(1..5]
|----[1L]
Każdy poziom wcięcia wskazuje ograniczenie stosowane do następnego klucza na liście. Nawiasy kwadratowe oznaczają zakres domknięty, a nawiasy okrągłe – zakres otwarty. W tym przypadku ograniczenie oznacza 1 < "a" <= 5, i
"b" = 1.
W tym przykładzie z wieloma gałęziami dla a,
ograniczenie odpowiada 1 < a <= 5 OR a = 10:
| constraints: /
|----(1L, 5L]
|----[10L]
Zmienne klucza
W niektórych węzłach skanowania (np. SequentialScan) występuje zarówno lista kluczy jako
część atrybutu index, jak i osobny atrybut keys w węźle Scan. Atrybut keys w węźle Scan oznacza nazwę zmiennej każdego klucza w definicji indeksu w odpowiedniej kolejności. Zmienne mogą służyć do odwoływania się do wartości skanowanego pola w czasie wykonywania w dalszej części drzewa wykonania.
W tym przykładzie wartość pola user w bieżącym dokumencie jest mapowana na zmienną $user_1, a wartość date_placed na $date_placed_1.
index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]
Węzły wykonania
Drzewo wykonania zapytania może zawierać te węzły.
SeekingScan
Reprezentuje skanowanie dynamiczne, w którym zwracane wiersze mogą nie znajdować się w jednym sekwencyjnym zakresie indeksu, a do spełnienia zapytania trzeba wykonać kilka odrębnych skanowań.
Na przykład zapytanie, w którym a istnieje, a b jest równe 1, działające na
indeksie ["a" ASC, "b" ASC], musiałoby skanować i zwracać osobny,
potencjalnie niesekwencyjny zakres dla każdej odrębnej wartości a.
Jest to bardziej wydajne niż pełne TableScan, ale mniej wydajne niż pojedyncze
SequentialScan na indeksie złożonym ["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
Reprezentuje skanowanie statycznego, sekwencyjnego zakresu wierszy w pamięci, które można wykonać w ramach jednej operacji odczytu.
key ordering length odnosi się do liczby kluczy, które muszą zostać zachowane
i zwrócone w oryginalnej kolejności kluczy. W przypadku schematu [k1, k2, k3] długość porządkowania kluczy równa 0 oznacza, że skanowanie może zwracać wyniki w dowolnej kolejności, 1 oznacza porządkowanie według k1, ale wiersze o tej samej wartości k1 mogą występować w dowolnej kolejności, a 3 zwraca dokumenty w dokładnej kolejności posortowanej.
• 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
Reprezentuje skanowanie statycznego, sekwencyjnego zakresu wierszy w pamięci z deduplikacją wierszy w pamięci.
• 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
IndexSeek
Reprezentuje skanowanie dynamiczne, w którym zwracane wiersze mogą być sparametryzowane przez dane w czasie wykonywania i mogą nie znajdować się w jednym sekwencyjnym zakresie indeksu, a do spełnienia zapytania trzeba wykonać kilka odrębnych skanowań.
Na przykład zapytanie, w którym user jest równe $user_id, a date_placed jest równe
"2025-08-10", działające na indeksie ["user" ASC, "date_placed" ASC], używałoby
wartości zmiennej $user_id w czasie wykonywania i ograniczenia "2025-08-10"
w przypadku date_placed do ograniczenia zakresów skanowania.
• IndexSeek
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| fields: [$user_1 ASC, $date_placed_1 ASC, $rid ASC]
| key: $key_1
| filter: $eq($user_1, $user_id) AND $eq($date_placed_1, "2025-08-10")
| records returned: 1
| records scanned: 1
Pobierz
Łączy identyfikator podanego wiersza z rzeczywistą zawartością wiersza z pamięci podstawowej. Węzeł Fetch jest wymagany, jeśli węzeł nadrzędny (lub ostateczny wynik zapytania) wymaga podzbioru pól z dokumentów.
• Fetch
| order: PRESERVE_INPUT_ORDER
| peak memory usage: 4.00 KiB (4,096 B)
| properties: *
| records returned: 1
TableScan
Pełne, nieuporządkowane skanowanie kolekcji. Używane, gdy zapytanie jest uruchamiane bez powiązanego indeksu.
Kolejność może być STABLE lub UNDEFINED, przy czym STABLE oznacza kolejność deterministyczną.
• TableScan
| order: STABLE
| properties: *
| records returned: 1
| records scanned: 1
| source: (default)#/**/collection
Zastosuj
Wykonuje łączenie między 2 zbiorami danych (input i map) przez iterowanie po każdym wierszu input i, w przypadku każdego wiersza, skanowanie i zwracanie wyników z map.
join_type wskazuje typ łączenia. Na przykład LEFT_OUTER oznacza, że wszystkie wiersze z input są uwzględniane w danych wyjściowych co najmniej raz.
Jeśli wiersz input nie znajdzie żadnych wyników z map, nadal będzie uwzględniany z wartościami null w kolumnach z map.
• Apply
| join_type: LEFT_OUTER
|
└── • input tree
| ...
└── • map tree
...
HashAggregate
Implementacja operacji agregujących oparta na haszowaniu. Wymaga zmaterializowania całej grupy w pamięci przed zwróceniem wyniku i nie może przekraczać limitu pamięci zapytania.
• HashAggregate
| aggregations: [sum($b_1) AS total]
| groups: [$a_1]
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 0
StreamAggregate
Specjalistyczny węzeł agregujący, który utrzymuje stan tylko dla jednej grupy naraz, co zmniejsza szczytowe wykorzystanie pamięci. Używany, gdy węzeł podrzędny zwraca grupy sekwencyjnie. Na przykład podczas grupowania według odrębnych wartości pola przy użyciu indeksu w tym polu.
• StreamAggregate
| keys: [foo ASC, bar ASC]
| properties: Selection { baz }
| aggregations: [$sum($foo_1) AS baz]
MajorSort
Wykonuje operację sortowania na stałym zbiorze właściwości. Materializuje wszystkie rekordy w pamięci naraz i zwraca posortowane wartości w kolejności. Rozmiar zbioru sortowania jest ograniczony przez limit pamięci zapytania.
Gdy podany jest kolejny limit, do zmniejszenia wykorzystania pamięci używany jest algorytm sortowania top-k. Dzięki niemu sortowanie można wykonywać na dowolnie dużym zbiorze rekordów, o ile pamięć używana do przechowywania k rozważanych elementów nie przekracza limitu.
• MajorSort
| fields: [a ASC, b DESC]
| limit: 10
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 1
Concat
Łączy wyniki wielu węzłów podrzędnych i zwraca wynik do węzła nadrzędnego. Ten węzeł nie deduplikuje wyników, które pojawiają się w wielu węzłach podrzędnych, a kolejność zwracanych wyników jest niedeterministyczna.
• Concat
├── • Fetch
...
├── • Fetch
Zasoby obliczeniowe
Oblicza zbiór wyrażeń, przypisując wyniki do zbioru zmiennych.
• Compute
| $user_1: user
| $full_name_1: str_concat($first_name_1, " ", $last_name_1)
| $address_1: UNSET
| records returned: 1
Filtr
Selektywnie zwraca wiersze tylko wtedy, gdy pasują one do podanego wyrażenia.
• Filter
| expression: $eq(foo, "bar")
| records returned: 1
RecordCount
Zlicza liczbę wierszy wygenerowanych przez węzeł podrzędny i emituje bieżącą liczbę do zmiennej określonej w atrybucie count.
• RecordCount
| count: $row_number_1
| records returned: 1
Wartości
Tworzy sekwencję wartości literałów, na których można pracować. Używany głównie wtedy, gdy zbiór dokumentów jest podawany jako dane wejściowe do zapytania.
• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]
Anuluj zagnieżdżenie
Anuluje zagnieżdżenie wartości wygenerowanej przez węzeł podrzędny.
• Unnest
| expression: foo AS unnested_foo
Limit
Ogranicza liczbę wierszy zwracanych do węzła nadrzędnego.
• Limit
| limit: 10
| records returned: 1
Odliczenie
Pomija określoną liczbę wierszy wygenerowanych przez węzeł podrzędny.
• Offset
| offset: 10
| records returned: 1