Introducción
En esta página, se describen los detalles sobre los operadores que se usan en Spanner Planes de ejecución de consultas. Para aprender a recuperar un plan de ejecución de un consulta específica con la consola de Google Cloud, lee 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:
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:
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:
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
un 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 buscar en todas las filas de una tabla. Esta
actual conduce a un análisis completo, y aparecen 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:
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
- Aplicación de mutaciones
- Creación por lotes
- datos
- Estructura de procesamiento
- Filtro
- Análisis de filtro
- Límite
- Asignación de ID aleatorio
- Serialización de resultados
- Orden
- TVF
- Entrada de la unión
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:
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:
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 procesamiento 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:
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:
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: La condición que admite búsquedas 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
yCol2
, entonces se puede buscar una cláusulaWHERE
que incluya valores explícitos paraCol1
, oCol1
yCol2
. En ese caso, Spanner solo lee datos 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:
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:
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 aleatoria produce un resultado mediante la lectura de 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 compatibles 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:
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 usa el muestreo de reservorio 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:
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:
Unspecified |
---|
[] |
[[Let's Get Back Together, COUNTRY], [Starting Again, ROCK]] |
[[Not About The Guitar, BLUES]] |
[] |
[] |
Este es el plan de ejecución:
El operador de serialización de resultados crea un resultado que contiene, para cada fila de
la tabla Singers
, un array de pares SongName
y SongGenre
para las canciones
por el 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:
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:
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 resultados mediante la lectura de las filas de entrada y la aplicación de la función especificada. La función podría 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 muestra 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 |
Rock | 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 |
Rock | Fight Story |
Este es el plan de ejecución:
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:
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:
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.
Unión de combinación
Un operador de unión de combinación es una implementación basada en combinaciones de una unión de SQL. Ambos lados
de las filas de producción de la unión ordenadas según las columnas utilizadas en la condición de la unión. El
Merge Join consume ambas transmisiones de entrada de forma simultánea y resultados de filas cuando el
se cumple la condición JOIN. Si las entradas no se ordenan originalmente como se requiere, el optimizador agrega operadores Sort
explícitos al plan.
El optimizador no selecciona automáticamente la opción Combinar 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:
En este plan de ejecución, la unión de combinación se distribuye para que se ejecute la unión
dónde están ubicados los datos. Esto también permite que la unión de combinación en este ejemplo opere sin la introducción de operadores de orden adicionales, ya que 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 SingerId_1
, AlbumId_1
del análisis del índice SongsBySingerAlbumSongNameDesc
del lado derecho.
Del mismo modo, el lado derecho avanza cada vez que es menor que el lado izquierdo. Este avance de combinación sigue buscando equivalencias para que se puedan mostrar las coincidencias resultantes.
Considera otro ejemplo de combinación de uniones con la siguiente consulta:
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:
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
de la consulta de este ejemplo solo está activada
AlbumId
, que no es la forma en que se almacenan los datos, por lo que se debe agregar un orden. El
el motor de consultas admite un algoritmo de combinación distribuida, lo que permite que se realice el ordenamiento.
de forma local y no global, 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 que no son de igualdad). Los planes de ejecución de combinación y unión pueden ser complejos debido a la ordenación adicional. y los requisitos de cumplimiento. El algoritmo principal de unión de combinación está adaptado para manejar variantes de unión interna, semi, anti y externa.
Unión de hash de transmisión push
Un operador de unión hash de transmisión de envío es una implementación distribuida de uniones de SQL basada en hash. El operador de unión hash de transmisión de envío lee filas del lado de entrada para construir un lote de datos. Luego, ese lote se transmite a todos los servidores que contienen datos del mapa. En los servidores de destino donde se recibe el lote de datos, se compila una unión hash con el lote como datos del lado de la compilación y, luego, se analizan los datos locales como el lado de sondeo de la unión hash.
El optimizador no selecciona automáticamente la unión hash de transmisión de envío. Para
usa este operador, establece 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:
La entrada de la unión de hash de transmisión push es el índice AlbumsByAlbumTitle
.
Esa entrada se serializa en un lote de datos. Luego, ese lote se envía a todos
las divisiones locales del índice SongsBySingerAlbumSongNameDesc
, en las que el lote
se deserializan y se compilan en una tabla 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 pueden filtrarse por una condición residual antes de que se devuelven. (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:
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 como 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:
El plan de ejecución contiene una subconsulta escalar, que se muestra como Subconsulta escalar, sobre un operador de agregación.
Spanner a veces convierte subconsultas escalares en otro operador, como como una unión o aplicación cruzada, para posiblemente 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 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:
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:
- Unión distribuida
- Unión de combinación distribuida
- Aplicación distribuida cruzada
- Aplicación distribuida externa
- Aplicación de mutaciones
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:
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:
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 ordenación combinada distribuida.
Una unión de combinación distribuida ejecuta los siguientes pasos:
El servidor raíz envía una subconsulta a cada servidor remoto que aloje un split de los datos consultados. La subconsulta incluye instrucciones para que los resultados se ordenen de una manera específica.
Cada servidor remoto ejecuta la subconsulta en su división y, luego, envía los resultados en el orden solicitado.
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 la versión 3 de Spanner y 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:
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:
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:
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:
En el plan de ejecución, los constructores de estructuras aparecen dentro de un operador de serialización de resultados.