Informacje o wykonywaniu zapytań

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