На этой странице объясняется результат выполнения запроса с помощью Query Explain. Чтобы узнать, как выполнить запрос с помощью Query Explain, см. раздел «Анализ выполнения запросов с помощью Query Explain» .
Общие понятия
В дереве выполнения используются следующие общие понятия и термины.
Строки и записи
Термины «строка» и «запись» используются для общего обозначения документа или записи в индексе.
Переменные
Символ $ обозначает переменную, которая создается или на которую ссылается дерево выполнения. Например: $foo_1 . Эти переменные обычно используются для ссылки на содержимое документа или значение выражения, вычисленного во время выполнения запроса.
В узлах выполнения могут присутствовать следующие внутренние переменные:
-
$__key__— это ключ, представляющий собой внутренний идентификатор документа. Это абсолютный, уникальный идентификатор, содержащий название проекта, базу данных и полный путь к документу. -
$__id__— это уникальный идентификатор документа в рамках его коллекции. Он уникален в пределах одной коллекции. -
$rid— идентификатор строки, представляющий собой внутренний идентификатор документа в хранилище. Он уникален в рамках одной коллекции.
Рассмотрим пример, где узел Compute используется для вычисления __id__ из __key__ документа:
Compute
| $__id__1: _id($__key__)
| records returned: 1
Ограничения и диапазоны
Некоторые узлы сканирования используют атрибуты constraints и ranges для описания диапазона сканируемых значений. Эти атрибуты используют формат дерева диапазонов, который содержит список значений. Эти значения соответствуют упорядоченному списку ключей, которые появляются в определении индекса. Например, первый диапазон, который появляется в дереве, здесь (1..5] , соответствует ограничениям на первом ключе, здесь a , в упорядоченном списке ключей:
| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
|----(1..5]
|----[1L]
Каждый уровень отступа указывает на ограничение, применяемое к следующему ключу в списке. Квадратные скобки обозначают диапазон, включающий его, круглые скобки — исключающий. В данном случае ограничение выражается как 1 < "a" <= 5 и "b" = 1 .
В следующем примере с несколькими ветвями для a ограничение соответствует 1 < a <= 5 OR a = 10 :
| constraints: /
|----(1L, 5L]
|----[10L]
Ключевые переменные
В некоторых узлах сканирования (например, SequentialScan ) в атрибуте index содержится как список ключей, так и отдельный атрибут keys в узле Scan . Атрибут keys в узле Scan обозначает имя переменной каждого ключа в определении индекса в порядке следования. Эти переменные можно использовать для ссылки на значения сканируемого поля, полученные во время выполнения, на более высоких уровнях дерева выполнения.
В следующем примере значение поля user для текущего документа сопоставляется с переменной $user_1 , а значение date_placed с переменной $date_placed_1 .
index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]
Узлы выполнения
Дерево выполнения запроса может содержать следующие узлы.
SeekingScan
Это динамический поиск, при котором возвращаемые строки могут не соответствовать одному последовательному диапазону индекса, и для удовлетворения запроса необходимо выполнить несколько отдельных поисков.
Например, запрос, в котором a существует и b равно 1 и работает с индексом ["a" ASC, "b" ASC] , потребует сканирования и возврата отдельного, потенциально непоследовательного диапазона для каждого уникального значения a . Это эффективнее, чем полное TableScan , но менее эффективно, чем однократное SequentialScan на составном индексе ["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
Представляет собой сканирование статического последовательного диапазона строк в памяти, которое может быть выполнено за одну операцию чтения.
key ordering length указывает на количество ключей, которые должны быть сохранены и возвращены в исходном порядке. Для схемы [k1, k2, k3] длина упорядочивания ключей, равная 0, означает, что сканирование может возвращать данные в любом порядке, 1 означает сортировку по k1, но строки с одинаковым значением k1 могут иметь любой порядок, 3 возвращает документы в точно отсортированном порядке.
• 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
| 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
ИндексПоиск
Это динамический поиск, при котором возвращаемые строки могут быть параметризованы данными, полученными во время выполнения, и могут не соответствовать одному последовательному диапазону индекса, а для удовлетворения запроса может быть выполнено несколько различных поисков.
Например, запрос, в котором user равен $user_id , а date_placed равен "2025-08-10" , выполняющийся по индексу ["user" ASC, "date_placed" ASC] , будет использовать значение переменной $user_id во время выполнения и ограничение "2025-08-10" для date_placed , чтобы ограничить диапазоны сканирования.
• 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
TableAccess
Выполняет обратное соединение идентификатора предоставленной строки с фактическим содержимым строки из основного хранилища. TableAccess необходим, если родительский узел (или конечный результат запроса) требует подмножества полей из документов.
• TableAccess
| order: PRESERVE_INPUT_ORDER
| peak memory usage: 4.00 KiB (4,096 B)
| properties: *
| records returned: 1
LookupById
Выполняет объединение, осуществляя поиск документов во внешней коллекции по их идентификатору (ID). Идентификаторы для поиска берутся из поля во входных документах. Результаты поиска добавляются в качестве нового поля во входные документы.
• LookupById
| local_field: $localField_1
| foreign_datasource: (default)#/**/foreign
| output: $output_1
TableScan
Полное, неупорядоченное сканирование коллекции. Используется, когда запрос выполняется без связанного с ним индекса.
Порядок может быть либо STABLE , либо UNDEFINED , при этом STABLE обозначает детерминированное упорядочение.
• TableScan
| order: STABLE
| properties: *
| records returned: 1
| records scanned: 1
| source: (default)#/**/collection
Применять
Выполняет объединение двух наборов данных ( input и map ), перебирая каждую строку input и, для каждой строки, сканируя и возвращая результаты со стороны map .
join_type указывает тип объединения. Например, LEFT_OUTER означает, что все строки из input будут включены в выходные данные хотя бы один раз. Если input строка не находит результатов со стороны map , она все равно будет включена, но со значениями null для столбцов со стороны map .
• Apply
| join_type: LEFT_OUTER
|
└── • input tree
| ...
└── • map tree
...
ХэшАгрегат
Реализация агрегатных операций с использованием хеширования. Требует материализации всей группы в памяти перед возвратом результата и не должна превышать лимит памяти запроса .
• HashAggregate
| aggregations: [sum($b_1) AS total]
| groups: [$a_1]
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 0
StreamAggregate
Специализированный агрегирующий узел, который поддерживает состояние только для одной группы за раз, что снижает пиковое потребление памяти. Используется, когда дочерний узел возвращает группы последовательно. Например, при группировке по уникальным значениям поля с использованием индекса по этому полю.
• StreamAggregate
| keys: [foo ASC, bar ASC]
| properties: Selection { baz }
| aggregations: [$sum($foo_1) AS baz]
MajorSort
Выполняет операцию сортировки по фиксированному набору свойств. Материализует все записи в памяти одновременно и возвращает отсортированные значения в порядке возрастания; размер отсортированного набора ограничен лимитом памяти для запросов .
При наличии последующего ограничения используется алгоритм сортировки по k элементам для уменьшения объема используемой памяти. С его помощью сортировку можно выполнять для произвольно большого набора записей, если объем памяти, используемый для хранения k рассматриваемых элементов, не превышает установленного лимита.
• MajorSort
| fields: [a ASC, b DESC]
| limit: 10
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 1
Конкат
Объединяет результаты нескольких дочерних узлов и возвращает результат родительскому узлу. Этот узел не удаляет дубликаты результатов, встречающихся в нескольких дочерних узлах, и порядок возвращаемых результатов непредсказуем.
• Concat
├── • TableAccess
...
├── • TableAccess
Вычислить
Выполняет оценку набора выражений, присваивая результаты набору переменных.
• Compute
| $user_1: user
| $full_name_1: str_concat($first_name_1, " ", $last_name_1)
| $address_1: UNSET
| records returned: 1
Фильтр
Возвращает строки выборочно только в том случае, если они соответствуют заданному выражению.
• Filter
| expression: $eq(foo, "bar")
| records returned: 1
RecordCount
Подсчитывает количество строк, созданных дочерним узлом, и выводит текущее значение в переменную, указанную в атрибуте count .
• RecordCount
| count: $row_number_1
| records returned: 1
Ценности
Создает последовательность литеральных значений для обработки. Используется преимущественно тогда, когда в качестве входных данных для запроса предоставляется список документов.
• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]
Гнездо
Выполняет встраивание значения, полученного от дочернего узла.
• Unnest
| expression: foo AS unnested_foo
Лимит
Ограничивает количество строк, возвращаемых родительскому узлу.
• Limit
| limit: 10
| records returned: 1
Компенсировать
Пропускает заданное количество строк, созданных дочерним узлом.
• Offset
| offset: 10
| records returned: 1