Referencia de ejecución de consultas

En esta página, se explica el resultado de una consulta ejecutada con Query Explain. Para obtener información sobre cómo ejecutar una consulta con la Explicación de consultas, consulta Analiza la ejecución de consultas con la Explicación de consultas.

Conceptos comunes

Los siguientes conceptos y términos comunes se utilizan en todo el árbol de ejecución.

Filas y registros

Los términos fila y registro se usan para hacer referencia de forma genérica a un documento o una entrada de índice.

Variables

Las siguientes variables internas pueden aparecer en los nodos de ejecución:

  • __key__: La clave es un identificador interno de un documento. Es un identificador absoluto y único que incluye el proyecto, la base de datos y la ruta de acceso completa del documento.
  • __id__: El ID es un identificador único para un documento dentro de su colección. Es único dentro de una sola colección.
  • __$0__…__$N__: Son variables específicas del contexto que se crean o a las que se hace referencia en el árbol de ejecución. Por lo general, estas variables se usan para hacer referencia al contenido de un documento o al valor de una expresión evaluada durante la ejecución de una búsqueda.

Considera un ejemplo en el que se usa un nodo de extensión para extraer el __id__ del documento __key__:

Extend
    |  expressions: [_id(__key__) AS __id__]
    |  records returned: 1

Restricciones y rangos

Algunos nodos de análisis usan los atributos constraints y ranges para describir el rango de valores que se analizan. Estos atributos usan un formato de árbol de rangos que contiene una lista de valores. Estos valores corresponden a la lista ordenada de claves que aparecen en la definición del índice. Por ejemplo, el primer rango que aparece en el árbol, aquí (1..5], corresponde a las restricciones de la primera clave, aquí a, en la lista ordenada de claves:

| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
               |----(1..5]
                    |----[1L]

Cada nivel de sangría indica la restricción que se aplica a la siguiente clave de la lista. Los corchetes representan un rango inclusivo, mientras que los paréntesis representan un rango exclusivo. En este caso, la restricción se traduce a 1 < "a" <= 5 y "b" = 1.

En el siguiente ejemplo con varias ramas para a, la restricción corresponde a 1 < a <= 5 OR a = 10:

| constraints: /
               |----(1L, 5L]
               |----[10L]

Variables clave

En algunos nodos de análisis (como SequentialScan), hay una lista de claves como parte del atributo index y un atributo keys independiente en el nodo Scan. El atributo keys en el nodo Scan denota el nombre de la variable de cada clave en la definición del índice, en orden. Las variables se pueden usar para hacer referencia a los valores de tiempo de ejecución del campo analizado más arriba en el árbol de ejecución.

En el siguiente ejemplo, el valor del campo user para el documento actual se asigna a la variable __$6__ y el valor de date_placed a __$7__.

index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __path__ ASC]
keys: [__$6__ ASC, __$7__ ASC, __path__ ASC]

Nodos de ejecución

Un árbol de ejecución de consultas puede contener los siguientes nodos.

SeekingScan

Representa un análisis dinámico en el que las filas que se muestran pueden no estar a lo largo de un solo rango secuencial del índice, y se deben realizar varios análisis distintos para satisfacer la consulta.

Por ejemplo, una consulta en la que a existe y b es igual a 1 que funciona en un índice de ["a" ASC, "b" ASC] debería analizar y devolver un rango independiente, y potencialmente no secuencial, para cada valor distinto de a. Esto es más eficiente que un TableScan completo, pero menos eficiente que un solo SequentialScan en un índice compuesto de ["b" ASC, "a" ASC].

• SeekingScan
| constraints: /
               |----(-∞..+∞)
                    |----[1L]
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, quantity ASC, __key__ ASC]
| keys: [__$1__ ASC, __$2__ ASC, __key__ ASC]
| properties: Selection { user }
| records returned: 1
| records scanned: 1

SequentialScan

Representa un análisis de un rango estático y secuencial de filas en el almacenamiento que se puede realizar en una sola operación de lectura.

El key ordering length hace referencia a la cantidad de claves que se deben conservar y devolver en el orden original de las claves. Para un esquema de [k1, k2, k3], una longitud de ordenamiento de claves de 0 significa que el análisis puede devolver resultados en cualquier orden, 1 significa que se ordena por k1, pero las filas con el mismo valor de k1 pueden aparecer en cualquier orden, y 3 devuelve documentos en el orden exacto de clasificación.

• SequentialScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| key ordering length: 3
| keys: [__$1__ ASC, __$2__ ASC, __key__ ASC]
| limit: 10
| properties: Selection { a }
| ranges: /
| records returned: 1
| records scanned: 1

UniqueScan

Representa un análisis de un rango estático y secuencial de filas en el almacenamiento con deduplicación en memoria de las filas.

• UniqueScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| keys: [__$1__ ASC, __$2__ ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
          |----(-∞..+∞)
| records returned: 1
| records scanned: 1

TableAccess

Realiza una unión inversa del identificador de la fila proporcionada con el contenido real de la fila del almacenamiento principal. TableAccess es obligatorio si un nodo principal (o el resultado final de la búsqueda) requiere un subconjunto de campos de los documentos.

• TableAccess
|  order: PRESERVE_INPUT_ORDER
|  peak memory usage: 4.00 KiB (4,096 B)
|  properties: *
|  records returned: 1

TableScan

Es un análisis completo y desordenado de una colección. Se usa cuando se ejecuta una consulta sin un índice asociado.

El orden puede ser STABLE o UNDEFINED, donde STABLE denota un orden determinístico.

• TableScan
|  order: STABLE
|  properties: *
|  records returned: 1
|  records scanned: 1
|  source: (default)#/**/collection

HashAggregate

Es la implementación respaldada por hash de las operaciones de agregación. Requiere materializar el grupo completo en la memoria antes de devolver el resultado y no debe exceder el límite de memoria de la consulta.

• HashAggregate
|  aggregations: [sum(__$0__) AS total]
|  groups: [a]
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 0

StreamAggregate

Es un nodo agregado especializado que solo mantiene el estado de un solo grupo a la vez, lo que reduce el uso máximo de memoria. Se usa cuando el nodo secundario subyacente devolverá grupos de forma secuencial. Por ejemplo, cuando se agrupan los datos por valores distintos de un campo mientras se usa un índice en ese campo.

• StreamAggregate
|  keys: [foo ASC, bar ASC]
|  properties: Selection { baz }
|  aggregations: [$sum(foo) AS baz]

MajorSort

Realiza una operación de ordenamiento en un conjunto fijo de propiedades. Materializa todos los registros en la memoria a la vez y devuelve los valores ordenados en orden. El tamaño del conjunto de ordenamiento está limitado por el límite de memoria de la consulta.

Cuando se proporciona un límite posterior, se usa un algoritmo de clasificación Top-K para reducir el uso de memoria. Con él, se pueden realizar ordenamientos en un conjunto de registros arbitrariamente grande, siempre y cuando la memoria que se usa para almacenar los k elementos considerados no supere el límite.

• MajorSort
|  fields: [a ASC, b DESC]
|  limit: 10
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 1

Concat

Concatena los resultados de varios nodos secundarios y devuelve el resultado al nodo principal. Este nodo no elimina los resultados duplicados que aparecen en varios elementos secundarios, y el orden de los resultados devueltos no es determinístico.

• Concat
├── • TableAccess
...
├── • TableAccess

Restringir

Proyecta un conjunto de propiedades para pasarlas a su nodo principal. Reduce el uso de memoria, ya que evita la propagación de campos no utilizados en cuanto dejan de ser relevantes para el resto de la búsqueda.

• Restrict
|  expressions: [foo AS foo, bar AS bar]
|  records returned: 0

Extender

Agrega un conjunto de campos a cada fila del conjunto de resultados. Se usa cuando se agregan campos a un documento y como nodo intermedio para admitir operaciones más complejas.

• Extend
|  expressions: ["bar" AS foo]
|  records returned: 1

Filtro

Devuelve filas de forma selectiva si y solo si coinciden con la expresión proporcionada.

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

Valores

Produce una secuencia de valores literales para trabajar. Se usa principalmente cuando se proporciona un conjunto de documentos como entrada para una búsqueda.

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

ReplaceWith

Reemplaza los campos de las filas que produce el nodo secundario por los campos de la expresión map proporcionada.

• ReplaceWith
|  map: map("full_name", str_concat(first_name, " ", last_name)), current_context())
|  records returned: 1

Unnest

Anula el anidamiento del valor que produce el nodo secundario.

• Unnest
|  expression: foo AS unnested_foo

Límite

Limita la cantidad de filas que se devuelven al nodo principal.

• Limit
|  limit: 10
|  records returned: 1

Desplazamiento

Omite una cantidad establecida de filas producidas por el nodo secundario.

• Offset
|  offset: 10
|  records returned: 1

Eliminar

Descarta un conjunto especificado de campos de los resultados que produce el nodo secundario.

• Drop
|  fields to drop: [__key__]
|  records returned: 1