Operadores de ejecución de consultas

Introducción

En esta página, se describen los detalles de los operadores que se usan en los planes de ejecución de consultas de Spanner. Si quieres aprender a recuperar un plan de ejecución para una consulta específica mediante la consola de Google Cloud, consulta Comprende cómo Spanner ejecuta consultas.

Las consultas y los planes de ejecución en esta página se basan en el siguiente esquema de base de datos:

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
  BirthDate  DATE
) PRIMARY KEY(SingerId);

CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);

CREATE TABLE Albums (
  SingerId        INT64 NOT NULL,
  AlbumId         INT64 NOT NULL,
  AlbumTitle      STRING(MAX),
  MarketingBudget INT64
) PRIMARY KEY(SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);

CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);

CREATE TABLE Songs (
  SingerId  INT64 NOT NULL,
  AlbumId   INT64 NOT NULL,
  TrackId   INT64 NOT NULL,
  SongName  STRING(MAX),
  Duration  INT64,
  SongGenre STRING(25)
) PRIMARY KEY(SingerId, AlbumId, TrackId),
  INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums;

CREATE INDEX SongsBySongName ON Songs(SongName);

CREATE TABLE Concerts (
  VenueId      INT64 NOT NULL,
  SingerId     INT64 NOT NULL,
  ConcertDate  DATE NOT NULL,
  BeginTime    TIMESTAMP,
  EndTime      TIMESTAMP,
  TicketPrices ARRAY<INT64>
) PRIMARY KEY(VenueId, SingerId, ConcertDate);

Puedes usar las siguientes declaraciones del lenguaje de manipulación de datos (DML) para agregar datos a estas tablas:

INSERT INTO Singers (SingerId, FirstName, LastName, BirthDate)
VALUES (1, "Marc", "Richards", "1970-09-03"),
       (2, "Catalina", "Smith", "1990-08-17"),
       (3, "Alice", "Trentor", "1991-10-02"),
       (4, "Lea", "Martin", "1991-11-09"),
       (5, "David", "Lomond", "1977-01-29");

INSERT INTO Albums (SingerId, AlbumId, AlbumTitle)
VALUES (1, 1, "Total Junk"),
       (1, 2, "Go, Go, Go"),
       (2, 1, "Green"),
       (2, 2, "Forever Hold Your Peace"),
       (2, 3, "Terrified"),
       (3, 1, "Nothing To Do With Me"),
       (4, 1, "Play");

INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre)
VALUES (2, 1, 1, "Let's Get Back Together", 182, "COUNTRY"),
       (2, 1, 2, "Starting Again", 156, "ROCK"),
       (2, 1, 3, "I Knew You Were Magic", 294, "BLUES"),
       (2, 1, 4, "42", 185, "CLASSICAL"),
       (2, 1, 5, "Blue", 238, "BLUES"),
       (2, 1, 6, "Nothing Is The Same", 303, "BLUES"),
       (2, 1, 7, "The Second Time", 255, "ROCK"),
       (2, 3, 1, "Fight Story", 194, "ROCK"),
       (3, 1, 1, "Not About The Guitar", 278, "BLUES");

Operadores de hoja

Un operador de hoja es aquel que no tiene operadores secundarios. Los tipos de operadores de hoja son:

Arreglo unnest

Un operador de arreglo unnest compacta el arreglo de entrada en filas de elementos. Cada fila resultante contiene hasta dos columnas: el valor real del arreglo y, opcional, la posición basada en cero en el arreglo.

Por ejemplo, con esta consulta:

SELECT a, b FROM UNNEST([1,2,3]) a WITH OFFSET b;

La consulta aplana el arreglo [1,2,3] en la columna a y muestra su posición en la columna b.

Estos son los resultados:

a b
1 0
2 1
3 2

Este es el plan de ejecución:

Operador de arreglo unnest

Relación de generación

Un operador de relación de generación muestra cero o más filas.

Relación de unidad

La relación de unidad muestra una fila. Es un caso especial del operador de relación de generación.

Por ejemplo, con esta consulta:

SELECT 1 + 2 AS Result;

El resultado es:

Result
3

Este es el plan de ejecución:

operador de relación de unidad

Relación vacía

La relación vacía no muestra filas. Es un caso especial del operador de relación de generación.

Por ejemplo, con esta consulta:

SELECT * FROM Albums LIMIT 0

El resultado es:

No results

Este es el plan de ejecución:

operador de relación vacía

Análisis

Un operador de análisis muestra filas mediante el análisis de una fuente de filas. Estos son los tipos de operadores de análisis:

  • Análisis de la tabla: El análisis se realiza en una tabla.
  • Análisis del índice: El análisis se realiza en un índice.
  • Análisis por lotes: El análisis se realiza en tablas intermedias creadas por otros operadores relacionales (por ejemplo, una tabla creada por una aplicación distribuida cruzada).

Siempre que sea posible, Spanner aplica predicados simples en las claves como parte del análisis. Los análisis se ejecutan de manera más eficaz cuando se aplican predicados porque el análisis no necesita leer toda la tabla o el índice. Los predicados aparecen en el plan de ejecución en el formato KeyPredicate: column=value.

En el peor de los casos, es posible que una consulta deba mirar todas las filas de una tabla. Esta situación genera un análisis completo y aparece en el plan de ejecución como full scan: true.

Por ejemplo:

SELECT s.LastName
FROM singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName = 'Catalina';

Estos son los resultados:

LastName
Smith

Este es el plan de ejecución:

operador de análisis

En el plan de ejecución, el operador principal de unión distribuida envía planes secundarios a servidores remotos. Cada subplan tiene un operador de serialización de resultados y un operador de análisis de índice. El predicado Key Predicate: FirstName = 'Catalina' restringe el análisis a las filas del índice SingersByFirstLastname en las que FirstName es igual a Catalina. El resultado del análisis de índice se muestra al operador de serialización de resultados.

Operadores unarios

Un operador unario es el operador que tiene un solo operador secundario relacional.

Los siguientes son operadores unarios:

Agregación

Un operador de agregación implementa instrucciones de SQL y funciones de agregación GROUP BY(como COUNT). La entrada de un operador de agregación está particionada de manera lógica en grupos organizados en columnas de claves (o en un solo grupo si GROUP BY no está presente). Para cada grupo, se procesan cero o más agregaciones.

Por ejemplo, con esta consulta:

SELECT s.SingerId, AVG(s.duration) AS average, COUNT(*) AS count
FROM Songs AS s
GROUP BY SingerId;

La consulta agrupa por SingerId y realiza una agregación AVG y una agregación COUNT.

Estos son los resultados:

SingerId average count
3 278 1
2 225,875 8

Este es el plan de ejecución:

operador de agregación

Los operadores de agregación pueden estar basados en hash o basados en el flujo. En el plan de ejecución anterior se muestra una agregación basada en transmisiones. Las transmisiones leen de entradas previamente ordenadas (si GROUP BY está presente) y procesan los grupos sin bloquearlos. Las agregaciones basadas en hash compilan tablas hash para mantener las agregaciones incrementales de varias filas de entrada de forma simultánea. Las agregaciones basadas en transmisiones son más rápidas y usan menos memoria que las agregaciones basadas en hash, pero requieren que la entrada se ordene (ya sea en columnas de claves o en índices secundarios).

Para situaciones distribuidas, un operador total se puede separar en un par local/global. Cada servidor remoto realiza la agregación local en sus filas de entrada y, luego, muestra los resultados en el servidor raíz. El servidor raíz realiza la agregación global.

Aplicación de mutaciones

Un operador de aplicación de mutaciones envía las mutaciones de una Declaración de lenguaje de manipulación de datos (DML) a la tabla. Es el operador principal en un plan de consulta para una declaración DML.

Por ejemplo, con esta consulta:

DELETE FROM Singers
WHERE FirstName = 'Alice';

Estos son los resultados:

4 rows deleted
This statement deleted 4 rows and did not return any rows.

Este es el plan de ejecución:

aplicación del operador de mutaciones

Creación por lotes

Un operador de creación por lotes agrupa por lotes sus filas de entrada en una secuencia. Por lo general, la operación se realiza como parte de una aplicación distribuida cruzada. Las filas de entrada se pueden volver a ordenar durante la agrupación por lotes. La cantidad de filas de entrada que se agrupan por lotes en cada ejecución del operador de lotes puede variar.

Consulta al operador de aplicación distribuida cruzada para ver un ejemplo de un operador de creación por lotes en un plan de ejecución.

Procesamiento

Un operador de compute produce resultados mediante la lectura de las filas de entrada y el agregado de una o más columnas adicionales que se procesan mediante expresiones escalares. Consulta el operador unir todo para ver un ejemplo del operador de procesamiento en un plan de ejecución.

Estructura de procesamiento

Un operador de estructura de procesamiento crea una variable para una estructura que contiene campos destinados a cada una de las columnas de entrada.

Por ejemplo, con esta consulta:

SELECT FirstName,
       ARRAY(SELECT AS STRUCT song.SongName, song.SongGenre
             FROM Songs AS song
             WHERE song.SingerId = singer.SingerId)
FROM singers AS singer
WHERE singer.SingerId = 3;

Estos son los resultados:

FirstName Unspecified
Alice [["Not About the Guitar","BLUES"]]

Este es el plan de ejecución:

operador de estructura de procesamiento

En el plan de ejecución, el operador de subconsulta del arreglo recibe la entrada desde un operador de unión distribuida, el cual recibe la entrada desde un operador de estructura de procesamiento. El operador de estructura de procesamiento crea una estructura a partir de las columnas SongName y SongGenre en la tabla Songs.

Filtro

Un operador de filtro lee todas las filas de su entrada, aplica un predicado escalar en cada una y, luego, solo muestra las filas que satisfacen el predicado.

Por ejemplo, con esta consulta:

SELECT s.LastName FROM (SELECT s.LastName
FROM Singers AS s LIMIT 3) s
WHERE s.LastName LIKE 'Rich%';

Estos son los resultados:

LastName
Richards

Este es el plan de ejecución:

operador de filtro

El predicado para cantantes cuyo apellido comienza con Rich se implementa como un filtro. La entrada del filtro es el resultado de un análisis de índice, y el resultado del filtro son las filas en las que LastName comienza con Rich.

Para el rendimiento, el filtro influye en la forma en que se leen los datos cada vez que uno se coloca directamente sobre un análisis. Por ejemplo, considera una tabla con la clave k. Un filtro con predicado k = 5 directamente por sobre un análisis de la tabla buscará filas que coincidan con k = 5, sin leer toda la entrada. Esto da como resultado una ejecución más eficiente de la consulta. En el ejemplo anterior, el operador de filtro solo lee las filas que satisfacen el predicado WHERE s.LastName LIKE 'Rich%'.

Análisis de filtro

Un operador de análisis de filtro siempre se encuentra por sobre un análisis de tabla o índice. Funciona junto con el análisis para reducir la cantidad de filas leídas de la base de datos, y el resultado suele ser más rápido que con un filtro. Spanner aplica el análisis de filtro en ciertas condiciones:

  • Condición de búsqueda: Esta condición se aplica si Spanner puede determinar una fila específica para acceder en la tabla. En general, esto sucede cuando el filtro está en un prefijo de la clave primaria. Por ejemplo, si la clave primaria está formada por Col1 y Col2, entonces se puede buscar una cláusula WHERE que incluya valores explícitos para Col1, o Col1 y Col2. En ese caso, Spanner lee datos solo dentro del rango de claves.
  • Condición residual: Cualquier otra condición en la que Spanner puede evaluar el análisis para limitar la cantidad de datos que se leen.

Por ejemplo, con esta consulta:

SELECT LastName
FROM Singers
WHERE SingerId = 1

Estos son los resultados:

LastName
Richards

Este es el plan de ejecución:

operador de análisis de filtro

Límite

Un operador de límite restringe la cantidad de filas que se muestran. El parámetro OFFSET opcional especifica la fila de inicio que se muestra. Para las situaciones distribuidas, un operador de límite se puede separar en un par local/global. Cada servidor remoto aplica el límite local para las filas de salida y, luego, muestra los resultados en el servidor raíz. El servidor raíz agrega las filas enviadas por los servidores remotos y, luego, aplica el límite global.

Por ejemplo, con esta consulta:

SELECT s.SongName
FROM Songs AS s
LIMIT 3;

Estos son los resultados:

SongName
Not About The Guitar
The Second Time
Starting Again

Este es el plan de ejecución:

operador límite

El límite local es el límite para cada servidor remoto. El servidor raíz agrega las filas de los servidores remotos y, luego, aplica el límite global.

Asignación de ID aleatorio

Un operador de asignación de ID aleatorio produce el resultado leyendo sus filas de entrada y agregando un número al azar a cada fila. Funciona con un operador Filter o Sort para lograr métodos de muestreo. Los métodos de muestreo admitidos son Bernoulli y Reservoir.

Por ejemplo, la siguiente consulta usa el muestreo de Bernoulli con una tasa de muestreo del 10%.

SELECT s.SongName
FROM Songs AS s TABLESAMPLE BERNOULLI (10 PERCENT);

Estos son los resultados:

SongName
Starting Again
Nothing Is The Same

Ten en cuenta que dado que el resultado es una muestra, puede variar cada vez que la consulta se ejecute, aunque sea la misma.

Este es el plan de ejecución:

operador de muestras de bernoulli

En este plan de ejecución, el operador de Random Id Assign recibe la entrada desde un operador de unión distribuida, el cual recibe la entrada desde un análisis del índice. El operador muestra las filas con ID aleatorios y el operador Filter aplica un predicado escalar en los ID aleatorios y muestra aproximadamente el 10% de las filas.

En el siguiente ejemplo, se utiliza el muestreo de Reservoir con una tasa de muestreo de 2 filas.

SELECT s.SongName
FROM Songs AS s TABLESAMPLE RESERVOIR (2 ROWS);

Estos son los resultados:

SongName
I Knew You Were Magic
The Second Time

Ten en cuenta que dado que el resultado es una muestra, puede variar cada vez que la consulta se ejecute, aunque sea la misma.

Este es el plan de ejecución:

operador de muestra de reservoir

En este plan de ejecución, el operador de Random Id Assign recibe la entrada desde un operador de unión distribuida, el cual recibe la entrada desde un análisis del índice. El operador muestra las filas con ID aleatorios y el operador Sort aplican el orden de clasificación en los ID aleatorios y aplican LIMIT con 2 filas.

Serialización de resultados

Un operador de serialización de resultados es un caso especial del operador de estructura de procesamiento que serializa cada fila del resultado final de la consulta para mostrarla al cliente.

Por ejemplo, con esta consulta:

SELECT ARRAY(SELECT AS STRUCT so.SongName, so.SongGenre
             FROM Songs AS so
             WHERE so.SingerId = s.SingerId)
FROM Singers AS s;

La consulta solicita un arreglo de SongName y SongGenre en función de SingerId.

Estos son los resultados:

Sin especificar
[]
[[Let's Get Back Together, COUNTRY], [Starting Again, ROCK]]
[[Not About The Guitar, BLUES]]
[]
[]

Este es el plan de ejecución:

Operador de serialización de resultados

El operador de serialización de resultados crea un resultado que contiene, en cada fila de la tabla Singers, un array de pares SongName y SongGenre para las canciones del cantante.

Orden

Un operador de orden lee las filas de entrada, las organiza por columnas y, luego, muestra los resultados ordenados.

Por ejemplo, con esta consulta:

SELECT s.SongGenre
FROM Songs AS s
ORDER By SongGenre;

Estos son los resultados:

SongGenre
BLUES
BLUES
BLUES
BLUES
CLASSICAL
COUNTRY
ROCK
ROCK
ROCK

Este es el plan de ejecución:

operador de orden

En este plan de ejecución, el operador de orden recibe las filas de entrada desde un operador de unión distribuida, ordena las filas de entrada y muestra las filas ordenadas al operador de resultado de serialización.

A fin de limitar la cantidad de filas que se muestran, un operador de orden puede tener los parámetros LIMIT y OFFSET como opción. Para situaciones distribuidas, un operador de ordenamiento con un operador LIMIT o OFFSET se divide en un par local/global. Cada servidor remoto aplica el orden de clasificación y el límite/desplazamiento local para sus filas de entrada y, luego, muestra los resultados en el servidor raíz. El servidor raíz agrega las filas enviadas por los servidores remotos, las ordena y, luego, aplica el límite/desplazamiento global.

Por ejemplo, con esta consulta:

SELECT s.SongGenre
FROM Songs AS s
ORDER By SongGenre
LIMIT 3;

Estos son los resultados:

SongGenre
BLUES
BLUES
BLUES

Este es el plan de ejecución:

operador de orden con límites

En el plan de ejecución se muestra el límite local para los servidores remotos y el límite global para el servidor raíz.

TVF

Un operador de función con valor de tabla produce un resultado mediante la lectura de las filas de entrada y la aplicación de la función especificada. La función puede implementar la asignación y mostrar la misma cantidad de filas que la entrada. También puede ser un generador que muestra más filas o un filtro que devuelve menos filas.

Por ejemplo, con esta consulta:

SELECT Genre, SongName
FROM ML.PREDICT(MODEL GenreClassifier, Table Songs)

Estos son los resultados:

Género SongName
País Not About The Guitar
Roca The Second Time
Pop Starting Again
Pop Nothing Is The Same
País Let's Get Back Together
Pop I Knew You Were Magic
Electrónicas Azul
Roca 42
Roca Fight Story

Este es el plan de ejecución:

operador tvf

Entrada de la unión

Un operador de entrada de la unión le muestra los resultados al operador unir todo. Consulta el operador unir todo para ver un ejemplo del operador de entrada de unión en un plan de ejecución.

Operadores binarios

Un operador binario es el que tiene dos operadores secundarios relacionales. Los siguientes son operadores binarios:

Aplicación cruzada

Un operador de aplicación cruzada ejecuta una consulta de tabla en cada fila recuperada por una consulta de otra tabla y muestra la unión de todas las ejecuciones de consulta de tabla. Los operadores de aplicación cruzada y de aplicación externa realizan el procesamiento orientado a filas, a diferencia de los operadores que ejecutan el procesamiento basado en conjuntos, como unión hash. El operador de aplicación cruzada tiene dos entradas, entrada y mapa. Dicho operador aplica cada fila del lado de entrada al lado del mapa. El resultado de la aplicación contiene columnas de los lados de entrada y mapa.

Por ejemplo, con esta consulta:

SELECT si.FirstName,
  (SELECT so.SongName
   FROM Songs AS so
   WHERE so.SingerId=si.SingerId
   LIMIT 1)
FROM Singers AS si;

La consulta solicita el nombre de cada cantante, junto con el nombre de solo una de sus canciones.

Estos son los resultados:

FirstName Unspecified
Alice Not About The Guitar
Catalina Let's Get Back Together
David NULL
Lea NULL
Marc NULL

La primera columna se propaga desde la tabla Singers y la segunda columna lo hace desde la tabla Songs. En los casos en que haya una SingerId en la tabla Singers pero no haya coincidencias de SingerId en la tabla Songs, la segunda columna contendrá NULL.

Este es el plan de ejecución:

operador de aplicación cruzada

El nodo de nivel superior es un operador de unión distribuida. El operador de unión distribuida reparte los planes secundarios a los servidores remotos. El subplan contiene un operador de serialización de resultados que procesa el nombre del cantante y el nombre de una de sus canciones, y serializa cada fila del resultado.

El operador de serialización de resultados recibe su entrada desde el operador de aplicación cruzada. El lado de entrada para el operador de aplicación cruzada es un análisis de tabla en la tabla Singers.

El lado del mapa de la operación de aplicación cruzada contiene lo siguiente (de arriba abajo):

  • Un operador de agregación que muestra Songs.SongName.
  • Un operador de límite que restringe la cantidad de canciones que se muestran a una por cantante.
  • Un análisis de índice en el índice SongsBySingerAlbumSongNameDesc.

El operador de aplicación cruzada asigna cada fila desde el lado de entrada a una fila en el lado del mapa que tiene el mismo SingerId. El resultado del operador de aplicación cruzada es el valor FirstName desde la fila de entrada y el valor SongName desde la fila del mapa. (El valor SongName será NULL si no hay ninguna fila del mapa que coincida con el SingerId). El operador de unión distribuida en la parte superior del plan de ejecución combina todas las filas de salida de los servidores remotos y los muestra como resultados de la consulta.

Unión hash

Un operador de unión hash es una implementación basada en hash de uniones de SQL. Las uniones de hash ejecutan el procesamiento basado en conjuntos. El operador de unión hash lee las filas de la entrada marcadas como compilación y las inserta en una tabla hash basada en una condición de unión. Luego, lee las filas de la entrada marcadas como sondeo. Para cada fila que se lee desde la entrada de sondeo, el operador busca las filas que coinciden en la tabla hash y las muestra como resultado.

Por ejemplo, con esta consulta:

SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=hash_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;

Estos son los resultados:

AlbumTitle SongName
Nothing To Do With Me Not About The Guitar
Verde The Second Time
Verde Starting Again
Verde Nothing Is The Same
Verde Let's Get Back Together
Verde I Knew You Were Magic
Verde Azul
Verde 42
Terrified Fight Story

Este es el plan de ejecución:

operador de unión hash

En el plan de ejecución, compilación es una unión distribuida que reparte los análisis en la tabla Albums. Sondeo es un operador de unión distribuida que reparte los análisis en el índice SongsBySingerAlbumSongNameDesc. El operador de unión hash lee todas las filas desde el lado de la compilación. Cada fila de compilación se coloca en una tabla hash basada en las columnas de la condición a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId. A continuación, el operador de unión hash lee todas las filas del lado del sondeo. Para cada fila de sondeo, el operador de unión hash busca coincidencias en la tabla hash. El operador de unión hash muestra las coincidencias resultantes.

En la tabla hash, estas también se pueden filtrar por una condición residual antes de que se muestren. (Un ejemplo de dónde aparecen las condiciones residuales es en las uniones que no son de igualdad). Los planes de ejecución de unión hash pueden ser complejos debido a la administración de memoria y a las variantes de unión. El algoritmo principal de unión hash está adaptado para manejar variantes de unión interna, semi, anti y externa.

Combinar unión

Un operador de unión de combinación es una implementación de unión de SQL basada en la combinación. Ambos lados de la unión producen filas ordenadas según las columnas usadas en la condición de la unión. La unión de combinación consume ambas transmisiones de entrada de forma simultánea y genera filas cuando se cumple la condición de la unión. Si las entradas no están ordenadas originalmente como se requiere, el optimizador agrega operadores Sort explícitos al plan.

El optimizador no selecciona automáticamente la unión de combinación. Para usar este operador, configura el método de unión en MERGE_JOIN en la sugerencia de consulta, como se muestra en el siguiente ejemplo:

SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=merge_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;

Estos son los resultados:

AlbumTitle SongName
Verde The Second Time
Verde Starting Again
Verde Nothing Is The Same
Verde Let's Get Back Together
Verde I Knew You Were Magic
Verde Azul
Verde 42
Terrified Fight Story
Nothing To Do With Me Not About The Guitar

Este es el plan de ejecución:

combinar operador de unión_1

En este plan de ejecución, la unión de combinación se distribuye de modo que la unión se ejecute donde se encuentran los datos. Esto también permite que la unión de combinación de este ejemplo opere sin la introducción de operadores de orden adicionales, porque ambos análisis de tablas ya están ordenados por SingerId, AlbumId, que es la condición de unión. En este plan, el análisis del lado izquierdo de la tabla Albums avanza cada vez que su SingerId, AlbumId es comparativamente menor que el par de SingerId_1, AlbumId_1 del análisis del índice de SongsBySingerAlbumSongNameDesc del lado derecho. De manera similar, el lado derecho avanza cuando es menor que el lado izquierdo. Este avance de combinación continúa buscando equivalencias, de modo que se puedan mostrar las coincidencias resultantes.

Considera otro ejemplo de merge join en el siguiente ejemplo:

SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=merge_join} Songs AS s
ON a.AlbumId = s.AlbumId;

Genera los siguientes resultados:

AlbumTitle SongName
Total Junk The Second Time
Total Junk Starting Again
Total Junk Nothing Is The Same
Total Junk Let's Get Back Together
Total Junk I Knew You Were Magic
Total Junk Azul
Total Junk 42
Total Junk Not About The Guitar
Verde The Second Time
Verde Starting Again
Verde Nothing Is The Same
Verde Let's Get Back Together
Verde I Knew You Were Magic
Verde Azul
Verde 42
Verde Not About The Guitar
Nothing To Do With Me The Second Time
Nothing To Do With Me Starting Again
Nothing To Do With Me Nothing Is The Same
Nothing To Do With Me Let's Get Back Together
Nothing To Do With Me I Knew You Were Magic
Nothing To Do With Me Azul
Nothing To Do With Me 42
Nothing To Do With Me Not About The Guitar
Play The Second Time
Play Starting Again
Play Nothing Is The Same
Play Let's Get Back Together
Play I Knew You Were Magic
Play Azul
Play 42
Play Not About The Guitar
Terrified Fight Story

Este es el plan de ejecución:

combinar operador__2 join

En el plan de ejecución anterior, el optimizador de consultas introdujo operadores Sort adicionales para lograr las propiedades necesarias para que se ejecute la unión de combinación. La condición JOIN en la consulta de este ejemplo solo está en AlbumId, que no es la forma en que se almacenan los datos, por lo que se debe agregar un orden. El motor de consultas admite un algoritmo de combinación distribuida, lo que permite que la ordenación se realice de forma local en lugar de globalmente, lo que distribuye y paraleliza el costo de la CPU.

Las coincidencias resultantes también se pueden filtrar por una condición residual antes de que se muestren. (Un ejemplo de dónde aparecen las condiciones residuales es en las uniones de no igualdad). Los planes de ejecución de combinación de combinaciones pueden ser complejos debido a requisitos de orden adicionales. El algoritmo de unión principal está adaptado para controlar variantes de unión interna, semi, anti y externa.

Unión hash de transmisión de envío

Un operador de unión de hash de transmisión de envío es una implementación distribuida basada en uniones de hash de uniones SQL. El operador de unión hash de transmisión de envío lee las filas del lado de la entrada para construir un lote de datos. Luego, ese lote se transmite a todos los servidores que contienen datos laterales del mapa. En los servidores de destino en los que se recibe el lote de datos, se crea una unión de hash con el lote como los datos de compilación. Luego, los datos locales se analizan como el lado de sondeo de la unión de hash.

El optimizador no selecciona automáticamente la Unión hash de transmisión de envío. Para usar este operador, configura el método de unión en PUSH_BROADCAST_HASH_JOIN en la sugerencia de consulta, como se muestra en el siguiente ejemplo:

SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=push_broadcast_hash_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;

Estos son los resultados:

AlbumTitle SongName
Verde The Second Time
Verde Starting Again
Verde Nothing Is The Same
Verde Let's Get Back Together
Verde I Knew You Were Magic
Verde Azul
Verde 42
Terrified Fight Story
Nothing To Do With Me Not About The Guitar

Este es el plan de ejecución:

Operador push_broadcast hash_join

La entrada de la unión hash de transmisión push es el índice AlbumsByAlbumTitle. Esa entrada se serializa en un lote de datos. Ese lote se envía a todas las divisiones locales del índice SongsBySingerAlbumSongNameDesc, donde el lote se deserializa y se compila en una tabla de hash. Luego, la tabla de hash usa los datos del índice local como un sondeo que muestra las coincidencias resultantes.

Las coincidencias resultantes también se pueden filtrar según una condición residual antes de que se muestren. (Un ejemplo de dónde aparecen las condiciones residuales es en las uniones que no son de igualdad).

Aplicación externa

Un operador de aplicación externa es similar a un operador de aplicación cruzada, excepto que, de ser necesario, el operador de aplicación externa crea una fila rellena con el valor NULL para garantizar que cada ejecución en el lado del mapa muestre al menos una fila. (En otras palabras, proporciona una semántica de combinación externa izquierda).

Operadores N-arios

Un operador N-ario es el que tiene más de dos operadores secundarios relacionales. Los siguientes son operadores N-arios:

Unir todo

Un operador unir todo combina todos los conjuntos de filas de sus operadores secundarios sin quitar los duplicados. Los operadores unir todo reciben sus entradas de operadores de entrada de la unión que se distribuyen en varios servidores. El operador unir todo requiere que sus entradas tengan el mismo esquema, es decir, el mismo conjunto de tipos de datos para cada columna.

Por ejemplo, con esta consulta:

SELECT 1 a, 2 b
UNION ALL
SELECT 3 a, 4 b
UNION ALL
SELECT 5 a, 6 b;

El tipo de fila para los operadores secundarios consta de dos números enteros.

Estos son los resultados:

a b
1 2
3 4
5 6

Este es el plan de ejecución:

union_all_operator

El operador unir todo combina sus filas de entrada y, en este ejemplo, envía los resultados al operador de serialización de resultados.

Una consulta como la siguiente funcionaría correctamente porque se usa el mismo conjunto de tipos de datos para cada columna, aunque los operadores secundarios usen variables diferentes para los nombres de las columnas:

SELECT 1 a, 2 b
UNION ALL
SELECT 3 c, 4 e;

Una consulta como la siguiente no tendría éxito porque los operadores secundarios usan tipos de datos diferentes para las columnas:

SELECT 1 a, 2 b
UNION ALL
SELECT 3 a, 'This is a string' b;

Subconsultas escalares

Una subconsulta escalar es una subexpresión de SQL que es parte de una expresión escalar. Spanner intenta quitar las subconsultas escalares siempre que sea posible. Sin embargo, en algunos casos, los planes pueden contener subconsultas escalares de manera explícita.

Por ejemplo, con esta consulta:

SELECT FirstName,
IF(FirstName='Alice',
   (SELECT COUNT(*)
    FROM Songs
    WHERE Duration > 300),
   0)
FROM Singers;

Esta es la subexpresión de SQL:

SELECT COUNT(*)
FROM Songs
WHERE Duration > 300;

Estos son los resultados (de la consulta completa):

FirstName
Alice 1
Catalina 0
David 0
Lea 0
Marc 0

Este es el plan de ejecución:

operador de subconsulta escalar

El plan de ejecución contiene una subconsulta escalar, que se muestra como Subconsulta escalar, sobre un operador de agregación.

A veces, Spanner convierte las subconsultas escalares en otro operador, como una unión o una aplicación cruzada, para mejorar el rendimiento.

Por ejemplo, con esta consulta:

SELECT *
FROM Songs
WHERE Duration = (SELECT MAX(Duration) FROM Songs);

Esta es la subexpresión de SQL:

SELECT MAX(Duration) FROM Songs;

Estos son los resultados (de la consulta completa):

SingerId AlbumId TrackId SongName Duration SongGenre
2 1 6 Nothing Is The Same 303 BLUES

Este es el plan de ejecución:

El operador de subconsulta escalar no se muestra en el plan

El plan de ejecución no contiene una subconsulta escalar porque Spanner convirtió la subconsulta escalar en una aplicación cruzada.

Subconsultas de arreglos

La subconsulta de arreglos es similar a una subconsulta escalar, excepto que se le permite a la subconsulta poder consumir más de una fila de entrada. Las filas consumidas se convierten en un único arreglo de salida escalar que contiene un elemento por cada fila de entrada consumida.

Por ejemplo, con esta consulta:

SELECT a.AlbumId,
ARRAY(SELECT ConcertDate
      FROM Concerts
      WHERE Concerts.SingerId = a.SingerId)
FROM Albums AS a;

Esta es la subconsulta:

SELECT ConcertDate
FROM Concerts
WHERE Concerts.SingerId = a.SingerId;

Los resultados de la subconsulta para cada AlbumId se convierten en un arreglo de filas de ConcertDate en comparación con las de AlbumId. El plan de ejecución contiene una subconsulta de arreglo, que se muestra como Subconsulta de arreglo, por encima de un operador de unión distribuida:

operador de subconsulta de arreglos

Operadores distribuidos

Los operadores antes descritos en esta página se ejecutan dentro de los límites de una sola máquina. Los operadores distribuidos se ejecutan en varios servidores.

Los siguientes son operadores distribuidos:

Un operador de unión distribuida es el operador básico a partir del cual se derivan las aplicaciones distribuidas cruzadas y las aplicaciones distribuidas externas.

Los operadores distribuidos aparecen en los planes de ejecución con una variante de unión distribuida sobre una o más variantes de unión distribuida local. Una variante de unión distribuida realiza la distribución remota de los subplanes. Una variante de unión distribuida local se encuentra encima de cada uno de los análisis realizados para la consulta, como se muestra en este plan de ejecución:

operador distribuido

Las variantes de unión distribuida local garantizan la ejecución estable de consultas cuando se producen reinicios para los límites de división que cambian de forma dinámica.

Siempre que sea posible, una variante de unión distribuida tiene un predicado dividido que da como resultado una depuración dividida; es decir, los servidores remotos ejecutan subplanes solo en las divisiones que satisfacen el predicado. Esto mejora la latencia y el rendimiento general de las consultas.

Unión distribuida

Un operador de unión distribuida divide de manera conceptual una o más tablas en varias divisiones, evalúa una subconsulta de manera independiente en cada división y, luego, unifica todos los resultados.

Por ejemplo, con esta consulta:

SELECT s.SongName, s.SongGenre
FROM Songs AS s
WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK';

Estos son los resultados:

SongName SongGenre
Starting Again ROCK
The Second Time ROCK
Fight Story ROCK

Este es el plan de ejecución:

operador de unión distribuida

Un operador de unión distribuida envía planes secundarios a servidores remotos, que realizan un análisis de tabla en divisiones que satisfacen el predicado WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK' de la consulta. Un operador de serialización de resultados procesa los valores de SongName y SongGenre desde las filas que muestran los análisis de tabla. Luego, el operador de unión distribuida muestra los resultados combinados de los servidores remotos como los resultados de la consulta de SQL.

Unión de combinación distribuida

El operador de unión de combinación distribuida distribuye una consulta en varios servidores remotos. Luego, combina los resultados de la consulta para producir un resultado ordenado, conocido como orden de combinación distribuido.

Una unión de combinación distribuida ejecuta los siguientes pasos:

  1. El servidor raíz envía una subconsulta a cada servidor remoto que aloja una división de los datos consultados. La subconsulta incluye instrucciones que indican que los resultados se ordenan en un orden específico.

  2. Cada servidor remoto ejecuta la subconsulta en su división y, luego, envía los resultados en el orden solicitado.

  3. El servidor raíz combina la subconsulta ordenada para producir un resultado completamente ordenado.

La unión de combinación distribuida está activada de forma predeterminada para Spanner versión 3 y versiones posteriores.

Aplicación distribuida cruzada

Un operador de aplicación distribuida cruzada (DCA) extiende el operador de aplicación cruzada mediante la ejecución en varios servidores. El lado de entrada del DCA agrupa los lotes de filas (a diferencia de un operador de aplicación cruzada normal, que actúa solo en una fila de entrada a la vez). El lado del mapa del DCA es un conjunto de operadores de aplicación cruzada que se ejecutan en servidores remotos.

Por ejemplo, con esta consulta:

SELECT AlbumTitle FROM Songs
JOIN Albums ON Albums.AlbumId=Songs.AlbumId;

Los resultados están en el formato:

AlbumTitle
Verde
Nothing To Do With Me
Play
Total Junk
Verde

Este es el plan de ejecución:

operador de aplicación distribuida cruzada

La entrada de DCA contiene un análisis del índice en el índice SongsBySingerAlbumSongNameDesc que agrupa las filas de AlbumId. El lado del mapa de este operador de aplicación cruzada es un análisis de índice en el índice AlbumsByAlbumTitle, sujeto al predicado de AlbumId en la fila de entrada que coincide con la clave AlbumId en el índice AlbumsByAlbumTitle. La asignación muestra el SongName para los valores SingerId en las filas de entrada por lotes.

Para resumir el proceso del DCA de este ejemplo, la entrada de la DCA son las filas por lotes de la tabla Albums y el resultado de la DCA es la aplicación de estas filas al mapa del análisis del índice.

Aplicación distribuida externa

Un operador de aplicación distribuida externa extiende el operador de aplicación externa mediante la ejecución de varios servidores, similar a la forma en que un operador de aplicación cruzada distribuida extiende a un operador de aplicación cruzada.

Por ejemplo, con esta consulta:

SELECT LastName, ConcertDate FROM Singers
LEFT OUTER JOIN@{JOIN_TYPE=APPLY_JOIN} Concerts
ON Singers.SingerId=Concerts.SingerId;

Los resultados están en el formato:

LastName ConcertDate
Trentor 2014-02-18
Smith 2011-09-03
Smith 2010-06-06
Lomond 2005-04-30
Martin 2015-11-04
Richards

Este es el plan de ejecución:

operador de aplicación externa distribuida

Aplicación de mutaciones

Un operador de aplicación de mutaciones envía las mutaciones de una Declaración de lenguaje de manipulación de datos (DML) a la tabla. Es el operador principal en un plan de consulta para una declaración DML.

Por ejemplo, con esta consulta:

DELETE FROM Singers
WHERE FirstName = 'Alice';

Estos son los resultados:

4 rows deleted
This statement deleted 4 rows and did not return any rows.

Este es el plan de ejecución:

aplicación del operador de mutaciones

Información adicional

En esta sección, se describen los elementos que no son operadores independientes, sino que ejecutan tareas para asistir a uno o más de los operadores que se mencionaron antes. Los elementos que se describen aquí son técnicamente operadores, pero no son operadores independientes en tu plan de consultas.

Constructor de estructura

Un constructor de estructura crea una estructura o una colección de campos. Por lo general, crea una estructura para las filas que resultan de una operación de procesamiento. Un constructor de estructura no es un operador independiente. En cambio, aparece en los operadores de estructura de procesamiento o de serialización de resultados.

Para una operación de estructura de procesamiento, el constructor crea una estructura destinada a que las columnas de las filas procesadas puedan usar una sola variable de referencia para la estructura.

Para una operación de serialización de resultados, el constructor de la estructura crea una estructura a fin de serializar los resultados.

Por ejemplo, con esta consulta:

SELECT IF(TRUE, struct(1 AS A, 1 AS B), struct(2 AS A , 2 AS B)).A;

Estos son los resultados:

A
1

Este es el plan de ejecución:

constructor de estructura

En el plan de ejecución, los constructores de estructuras aparecen dentro de un operador de serialización de resultados.