Informacje o wykonywaniu zapytań

Na tej stronie znajdziesz objaśnienie danych wyjściowych zapytania wykonanego za pomocą funkcji wyjaśniania zapytań. Aby dowiedzieć się, jak wykonać zapytanie za pomocą funkcji Query Explain, zapoznaj się z artykułem Analizowanie wykonywania zapytań za pomocą funkcji Query Explain.

Typowe pojęcia

W drzewie wykonywania używane są te typowe pojęcia i terminy.

Wiersze i rekordy

Terminy wiersz i rekord są używane do ogólnego odwoływania się do dokumentu lub wpisu indeksu.

Zmienne

$ oznacza zmienną, która jest tworzona lub do której odwołuje się drzewo wykonywania. Na przykład: $foo_1. Te zmienne są zwykle używane do odwoływania się do zawartości dokumentu lub wartości wyrażenia ocenianego podczas wykonywania zapytania.

W węzłach wykonywania mogą pojawiać się te zmienne wewnętrzne:

  • $__key__ – klucz jest wewnętrznym identyfikatorem dokumentu. Jest to bezwzględny, unikalny identyfikator z projektem, bazą danych i pełną ścieżką dokumentu.
  • $__id__ – identyfikator to unikalny identyfikator dokumentu w kolekcji. Jest on unikalny w ramach jednej kolekcji.
  • $rid – identyfikator wiersza to wewnętrzny identyfikator dokumentu w miejscu przechowywania. Jest on unikalny w ramach jednej kolekcji.

Rozważmy przykład, w którym węzeł Compute jest używany do obliczania __id__ z 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. Wartości te odpowiadają liście uporządkowanej kluczy, które pojawiają się w definicji indeksu. Na przykład pierwszy zakres, który pojawia się w drzewie, tutaj (1..5], odpowiada ograniczeniom pierwszego klucza, tutaj a, na liście uporządkowanej 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, które dotyczy następnego klucza na liście. Nawiasy kwadratowe oznaczają przedział domknięty, a nawiasy okrągłe – przedział otwarty. W tym przypadku ograniczenie przekłada się na 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 (takich jak SequentialScan) znajduje się zarówno lista kluczy w ramach 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 kolejności. Zmienne mogą służyć do odwoływania się do wartości czasu działania skanowanego pola w górnej części drzewa wykonywania.

W tym przykładzie wartość pola user dla bieżącego dokumentu 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 wykonawcze

Drzewo wykonywania 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 wykonania zapytania konieczne jest przeprowadzenie wielu różnych 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 przeskanować i zwrócić oddzielny, potencjalnie niesekwencyjny zakres dla każdej odrębnej wartości a. Jest to bardziej wydajne niż pełne zapytanie TableScan, ale mniej wydajne niż pojedyncze zapytanie SequentialScan w indeksie wieloskładnikowym ["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 pierwotnej kolejności. 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 z tą samą wartością k1 mogą być wyświetlane w dowolnej kolejności, a 3 zwraca dokumenty w dokładnie posortowanej kolejności.

• 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 masowej 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ć parametryzowane przez dane środowiska wykonawczego i mogą nie znajdować się w jednym sekwencyjnym zakresie indeksu, a do wykonania zapytania może być konieczne przeprowadzenie wielu różnych skanowań.

Na przykład zapytanie, w którym user jest równe $user_id, a date_placed jest równe "2025-08-10", uruchomione na indeksie ["user" ASC, "date_placed" ASC], użyje wartości zmiennej $user_id w czasie działania i ograniczenia "2025-08-10" na date_placed, aby ograniczyć zakresy 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: equal($user_1, $user_id) AND equal($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. 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

LookupById

Wykonuje połączenie, wyszukując dokumenty w kolekcji zewnętrznej według ich identyfikatora. Identyfikatory do wyszukania są pobierane z pola w dokumentach wejściowych. Wyniki wyszukiwania są dodawane jako nowe pole do dokumentów wejściowych.

• LookupById
|  local_field: $localField_1
|  foreign_datasource: (default)#/**/foreign
|  output: $output_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

NestedLoopJoin

Wykonuje połączenie między 2 zbiorami danych (lewym i prawym), iterując po każdym wierszu lewego zbioru danych wejściowych i skanując prawy zbiór danych wejściowych pod kątem pasujących wierszy na podstawie join_condition.

join_type wskazuje typ połączenia. Na przykład LEFT_OUTER oznacza, że wszystkie wiersze z lewej strony danych wejściowych są uwzględniane co najmniej raz w danych wyjściowych. Jeśli wiersz po lewej stronie nie pasuje do żadnego wiersza w danych wejściowych po prawej stronie na podstawie join_condition, nadal będzie uwzględniany, a kolumny z danymi wejściowymi po prawej stronie będą miały wartości null.

• NestedLoopJoin
|  join_type: LEFT_OUTER
|  join_condition: equal($left, $right)
|
└── • left tree
|     ...
└── • right tree
      ...

HashAggregate

Implementacja operacji agregacji oparta na hashach. Wymaga to 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ł agregacji, który utrzymuje stan tylko dla jednej grupy naraz, co zmniejsza szczytowe wykorzystanie pamięci. Używane, gdy podrzędny węzeł bazowy będzie zwracać grupy sekwencyjnie. Na przykład podczas grupowania według różnych 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 zestawie 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 temu można sortować dowolnie duży zbiór 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 usuwa duplikatów 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

Ocenia zestaw wyrażeń, przypisując wyniki do zestawu zmiennych.

• Compute
|  $user_1: user
|  $full_name_1: str_concat($first_name_1, " ", $last_name_1)
|  $address_1: UNSET
|  records returned: 1

Filtr

Zwraca wybiórczo wiersze tylko wtedy, gdy pasują do podanego wyrażenia.

• Filter
|  expression: $eq(foo, "bar")
|  records returned: 1

RecordCount

Zlicza liczbę wierszy wygenerowanych przez węzeł podrzędny i wysyła bieżącą liczbę do zmiennej określonej w atrybucie count.

• RecordCount
|  count: $row_number_1
|  records returned: 1

Wartości

Generuje sekwencję literałów, na których można pracować. Używany głównie wtedy, gdy jako dane wejściowe zapytania podawany jest określony zestaw dokumentów.

• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]

Anuluj zagnieżdżenie

Cofa 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

Przesunięcie

Pomija określoną liczbę wierszy wygenerowanych przez węzeł podrzędny.

• Offset
|  offset: 10
|  records returned: 1