Operadores de execução de consulta

Introdução

Esta página contém os detalhes sobre os operadores usados nos planos de execução da consulta do Cloud Spanner. Para saber como recuperar um plano de execução para uma consulta específica usando o Console do GCP, consulte Noções básicas sobre como o Cloud Spanner executa consultas.

As consultas e os planos de execução neste tópico são baseados no esquema de banco de dados a seguir:

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);

Operadores folha

Um operador folha é um operador que não tem filhos. Os tipos de operadores folha são:

Array unnest

Com um operador array unnest é possível nivelar uma matriz de entrada em linhas de elementos. Em cada linha resultante há até duas colunas: o valor real da matriz e, opcionalmente, a posição baseada em zero na matriz.

Por exemplo, para esta consulta:

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

A matriz [1,2,3] é nivelada pela consulta na coluna a e a posição da matriz é mostrada na coluna b.

Estes são os resultados:

a b
1 0
2 1
3 2

Este é o plano de execução:

operador array unnest

Generate relation

Um operador generate relation retorna zero ou mais linhas.

Unit relation

Unit relation retorna uma linha. É um caso especial do operador generate relation.

Por exemplo, para esta consulta:

SELECT 1 + 2 AS Result;

O resultado é:

Result
3

Este é o plano de execução:

operador unit relation

Empty relation

Empty relation não retorna nenhuma linha. É um caso especial do operador generate relation.

Por exemplo, para esta consulta:

SELECT * FROM Albums LIMIT 0

O resultado é:

No results

Este é o plano de execução:

operador empty relation

Scan

O operador scan retorna linhas por meio da verificação de uma fonte de linhas. Estes são os tipos de operadores scan:

  • Table scan: a verificação ocorre em uma tabela.
  • Index scan: a verificação ocorre em um índice.
  • Batch scan: a verificação ocorre em tabelas intermediárias criadas por outros operadores relacionais. Por exemplo, uma tabela criada por um operador distributed cross apply.

Com o Cloud Spanner, sempre que possível são aplicados predicados simples em chaves como parte de uma verificação. As verificações são executadas de modo mais eficiente quando os predicados são aplicados porque não é necessário que a tabela ou índice inteiros sejam lidos pela verificação. Os predicados aparecem no plano de execução na forma KeyPredicate: column=value.

Por exemplo, para esta consulta:

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

Estes são os resultados:

LastName
Smith

Este é o plano de execução:

operador scan

No plano de execução, com o operador distributed union de nível superior, são enviados subplanos a servidores remotos. Em cada subplano há um operador serialize result e um operador index scan. Com o predicado Key Predicate: FirstName = 'Catalina', a verificação fica restrita às linhas do índice SingersByFirstLastname que tenham FirstName igual a Catalina. A saída de index scan é retornada para o operador serialize result.

Operadores unários

Um operador unário é um operador que tem um único filho relacional.

Os seguintes operadores são unários:

Aggregate

Um operador aggregate implementa as instruções SQL GROUP BY e funções de agregação como COUNT. A entrada de um operador aggregate é dividida logicamente em grupos organizados em colunas de chave ou em um único grupo, se GROUP BY não estiver presente. Zero ou mais agregados são computados para cada grupo.

Por exemplo, para esta consulta:

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

Com a consulta é feito o agrupamento por SingerId e são feitas as agregações AVG e COUNT.

Estes são os resultados:

SingerId average count
3 278 1
2 225.875 8

Os resultados são agregados por SingerId e cada grupo é organizado pelas colunas average e count.

Este é o plano de execução:

operador aggregate

Os operadores aggregate podem ser baseados em stream ou baseados em hash. O plano de execução acima mostra um agregado baseado em stream. Os agregados baseados em stream são lidos a partir da entrada já pré-classificada (se GROUP BY estiver presente) e computam os grupos sem bloquear. Os agregados baseados em hash criam tabelas de hash para manter agregados incrementais de várias linhas de entrada simultaneamente. Os agregados baseados em stream são mais rápidos e usam menos memória do que os agregados baseados em hash, mas exigem que a entrada seja classificada por colunas de chave ou índices secundários.

Para cenários distribuídos, um operador aggregate pode ser separado em um par local/global. A agregação local é executada individualmente pelos servidores remotos nas respectivas linhas de entrada e, em seguida, os resultados são retornados ao servidor raiz. No servidor raiz é executada a agregação global.

Apply Mutations

Um operador apply mutations aplica as mutações de uma linguagem de manipulação de dados (DML, na sigla em inglês) à tabela. Ele é o operador principal em um plano de consulta para uma instrução DML.

Por exemplo, para esta consulta:

DELETE FROM Singers
WHERE FirstName = 'Alice'

Estes são os resultados:

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

Este é o plano de execução:

operador apply mutations

Create batch

Um operador create batch reúne as linhas de entrada em sequência. Uma operação create batch geralmente ocorre como parte de uma operação distributed cross apply. É possível reordenar as linhas de entrada durante o processamento de lotes. O número de linhas de entrada que são agrupadas em cada execução do operador de lote é variável.

Consulte o operador distributed cross apply para ver um exemplo de operador create batch em um plano de execução.

Compute

A saída de um operador compute é produzida com a leitura das linhas de entrada e a adição de uma ou mais colunas extras que são computadas por meio de expressões escalares. Consulte o operador union all para ver um exemplo do operador compute em um plano de execução.

Compute struct

Com um operador compute struct é possível criar uma variável para uma estrutura contendo campos para cada uma das colunas de entrada.

Por exemplo, para esta consulta:

SELECT FirstName,
ARRAY(SELECT AS STRUCT a.AlbumTitle, a.ReleaseDate
      FROM Albums AS a
      WHERE a.SingerId = s.SingerId)
FROM singers AS s

Estes são os resultados:

FirstName Unspecified
Marc [["Total Junk",2015-03-01],["Go, Go, Go",2017-02-01]]
Catalina [["Green",2016-11-01]]
Alice [["Nothing To Do With Me",2016-09-01]]
Lea [["Play",2015-03-01]]

Este é o plano de execução:

operador compute struct

No plano de execução, a entrada de um operador compute struct é recebida pelo operador array subquery. No operador compute struct é criada uma estrutura a partir das colunas AlbumTitle e ReleaseDate da tabela Albums.

Filter

Com um operador filter, todas as linhas da entrada são lidas, um predicado escalar é aplicado a cada linha e apenas as linhas que satisfazem ao predicado são retornadas.

Por exemplo, para esta consulta:

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

Estes são os resultados:

LastName
Richards

Este é o plano de execução:

operador filter

O predicado para cantores cujo sobrenome começa com Rich é implementado como um filtro. A entrada do filtro é a saída de uma operação index scan, e a saída do filtro são as linhas em que LastName começa com Rich.

Para fins de desempenho, sempre que um filtro é posicionado diretamente acima de uma operação scan, o filtro afeta o modo como os dados são lidos. Por exemplo, considere uma tabela com a chave k. Um filtro com o predicado k = 5 diretamente acima de uma operação scan da tabela procura linhas que correspondam a k = 5, sem ler a entrada inteira. Com isso, a execução da consulta fica mais eficiente. No exemplo acima, com o operador "filter" são lidas apenas as linhas que satisfazem ao predicado WHERE s.LastName LIKE 'Rich%'.

Filter scan

Um operador filter scan está sempre acima de um table ou index scan. Ele opera com a verificação para reduzir o número de linhas lidas no banco de dados, e a verificação resultante é normalmente mais rápida do que com um filter. O Cloud Spanner aplica esse operador em certas condições:

  • Condição pesquisável: a condição pesquisável se aplica se o Cloud Spanner puder determinar uma linha específica para acessar na tabela. Em geral, isso acontece quando o filtro está em um prefixo da chave primária. Por exemplo, se a chave primária consistir de Col1 e Col2, uma cláusula WHERE que inclua valores explícitos para Col1 ou Col1 e Col2 será pesquisável. Nesse caso, o Cloud Spanner lê dados somente dentro do intervalo de chaves.
  • Condição residual: qualquer outra condição em que o Cloud Spanner possa avaliar a verificação para limitar a quantidade de dados lidos.

Por exemplo, para esta consulta:

SELECT LastName
FROM Singers
WHERE SingerId = 1

Estes são os resultados:

LastName
Richards

Este é o plano de execução:

operador filter scan

Limit

Um operador limit restringe o número de linhas retornadas. Um parâmetro OFFSET opcional especifica a linha inicial a ser retornada. Em cenários distribuídos, é possível separar um operador "limit" em um par local/global. Em cada servidor remoto é aplicado o limite local às linhas de saída e os resultados são retornados ao servidor raiz. No servidor raiz as linhas enviadas pelos servidores remotos são agregadas e o limite global é aplicado.

Por exemplo, para esta consulta:

SELECT s.SongName
FROM Songs AS s
LIMIT 3;

Estes são os resultados:

SongName
Not About The Guitar
The Second Time
Starting Again

Este é o plano de execução:

operador limit

O limite local é aquele de cada servidor remoto. As linhas dos servidores remotos são agregadas pelo servidor raiz e, em seguida, o limite global é aplicado.

Sample

Um operador sample retorna um subconjunto da entrada com base em uma amostragem das linhas de entrada. Os métodos compatíveis de amostragem são Bernoulli e Reservoir.

Por exemplo, para esta consulta:

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

A consulta usa a amostragem Bernoulli com uma taxa de amostragem de 10 por cento.

Estes são os resultados:

SongName
Starting Again
Nothing Is The Same

Observe que, por ser uma amostra, o resultado pode variar toda vez que a consulta for executada, embora a consulta seja a mesma.

Este é o plano de execução:

operador sample

Neste plano de execução, o operador "sample" recebe a entrada de um index scan. O operador "sample" retorna as linhas de amostra para um operador serialize result.

Serialize result

Um operador serialize result é um caso especial do operador "compute struct" que serializa cada linha do resultado final da consulta para retorno ao cliente.

Por exemplo, para esta consulta:

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

A consulta solicita uma matriz de SongName e SongGenre com base em SingerId.

Estes são os resultados:

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

Este é o plano de execução:

Operador serialize result

O operador "serialize result" cria um resultado que contém SongName e SongGenre para cada linha da tabela Songs.

Sort

Um operador sort lê as linhas de entrada, as ordena por colunas e, em seguida, retorna os resultados classificados.

Por exemplo, para esta consulta:

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

Estes são os resultados:

SongName
42
Blue
Fight Story
I Knew You Were Magic
Let Us Get Back Together
Not About The Guitar
Nothing Is The Same
Starting Again
The Second Time

Este é o plano de execução:

operador sort

Neste plano de execução, as linhas de entrada de um operador "sort" são recebidas de um distributed union e classificadas. Em seguida, elas são retornadas a um operador serialize result.

Para restringir o número de linhas retornadas, um operador "sort" pode opcionalmente ter os parâmetros LIMIT e OFFSET. Em cenários distribuídos, um operador "sort" com um operador LIMIT e/ou OFFSET é separado em um par local/global. Cada servidor remoto aplica a ordem de classificação e o limite/deslocamento local para as linhas de entrada e, em seguida, retorna os resultados ao servidor raiz. O servidor raiz agrega as linhas enviadas pelos servidores remotos, as classifica e, em seguida, aplica o limite/deslocamento global.

Por exemplo, para esta consulta:

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

Estes são os resultados:

SongName
42
Blue
Fight Story

Este é o plano de execução:

operador sort com limit

O plano de execução mostra o limite local dos servidores remotos e o limite global do servidor raiz.

Union input

Um operador union input retorna resultados para o operador union all. Consulte o operador union all para ver um exemplo do operador "union input" em um plano de execução.

Operadores binários

Um operador binário é um operador que tem dois filhos relacionais. Os seguintes operadores são binários:

Cross apply

Um operador cross apply executa uma consulta de tabela em cada linha recuperada por uma consulta de outra tabela e retorna a união de todas as execuções da consulta de tabela. Os operadores "cross apply" e outer apply executam o processamento orientado por linha, em vez do processamento baseado em conjunto, como hash join, que é executado por outros operadores. O operador cross apply tem duas entradas, input e map. O operador cross apply aplica cada linha do lado "input" ao lado "map". O resultado de "cross apply" tem colunas de ambos os lados: "input" e "map".

Por exemplo, para esta consulta:

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

A consulta pede o nome de cada cantor, juntamente com o nome de apenas uma das canções do cantor.

Estes são os resultados:

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

A primeira coluna é preenchida a partir da tabela Singers, e a segunda coluna é preenchida a partir da tabela Songs. Caso haja um SingerId na tabela Singers, mas não exista um SingerId correspondente na tabela Songs, a segunda coluna conterá NULL.

Este é o plano de execução:

operador cross apply

O nó de nível superior é um operador distributed union. O operador "distributed union" distribui subplanos a servidores remotos. O subplano contém um operador serialize result, que computa o nome do cantor e o nome de uma das canções dele e serializa cada linha da saída.

O operador "serialize result" recebe a entrada de um operador "cross apply". O lado "input" do operador "cross apply" é uma operação scan na tabela Singers.

O lado "map" da operação "cross apply" contém os seguintes itens (de cima para baixo):

  • Um operador aggregate que retorna Songs.SongName.
  • um operador limit que limita o número de canções retornadas a uma por cantor.
  • Um operador index scan no índice SongsBySingerAlbumSongNameDesc

O operador "cross apply" associa cada linha do lado "input" a uma linha do lado "map" que tenha o mesmo SingerId. A saída do operador "cross apply" é o valor FirstName da linha de "input" e o valor SongName da linha de "map". O valor SongName será NULL se não houver nenhuma linha de "map" que corresponda ao SingerId. Em seguida, o operador "distributed union", na parte superior do plano de execução, combina todas as linhas de saída dos servidores remotos e as retorna como resultados da consulta.

Hash join

Um operador hash join é uma implementação baseada em hash de junções SQL. Operações "hash join" executam processamento baseado em conjunto. O operador "hash join" lê as linhas da entrada marcadas como build e as insere em uma tabela de hash com base em uma condição de junção. Em seguida, o operador "hash join" lê as linhas da entrada marcadas como probe. Para cada linha que lê a partir da entrada "probe", o operador "hash join" procura as linhas correspondentes na tabela de hash. O operador "hash join" retorna as linhas correspondentes como resultado.

Por exemplo, para esta consulta:

SELECT a.AlbumTitle, s.SongName
FROM Albums AS a HASH JOIN Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;

Estes são os resultados:

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

Este é o plano de execução:

operador hash join

No plano de execução, build é um distributed union que distribui scans na tabela Albums. Probe é um operador "distributed union" que distribui "scans" no índice SongsBySingerAlbumSongNameDesc. O operador hash join lê todas as linhas do lado build. Cada linha "build" é colocada em uma tabela de hash com base nas colunas na condição a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId. Em seguida, o operador hash join lê todas as linhas do lado probe. Para cada linha "probe", o operador "hash join" procura correspondências na tabela de hash. As correspondências resultantes são retornadas pelo operador "hash join".

As correspondências resultantes na tabela de hash também podem ser filtradas por uma condição residual antes de serem retornadas. Um exemplo de onde as condições residuais aparecem é em junções de não igualdade. Os planos de execução de "hash join" podem ser complexos devido ao gerenciamento de memória e às variantes de junção. O principal algoritmo de "hash join" é adaptado para lidar com as variantes "inner", "semi", "anti" e "outer join".

Outer apply

Um operador outer apply é semelhante ao cross apply, mas em um operador "outer apply" pelo menos uma linha é retornada após a execução no lado "map" e, se necessário, uma linha preenchida com NULL é criada. Em outras palavras, fornece semântica de "left outer join".

Operadores N-ários

Um operador N-ário é um operador que tem mais de dois filhos relacionais. Os seguintes operadores são N-ários:

Union all

Um operador union all combina todos os conjuntos de linhas dos filhos sem remover duplicatas. Os operadores "union all" recebem a entrada de operadores union input distribuídos em vários servidores. O operador "union all" exige que as entradas tenham o mesmo esquema, ou seja, o mesmo conjunto de tipos de dados para cada coluna.

Por exemplo, para esta consulta:

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

O tipo de linha dos filhos consiste em dois inteiros.

Estes são os resultados:

a b
1 2
3 4
5 6

Este é o plano de execução:

union_all_operator

O operador "union all" combina as linhas de entrada e, neste exemplo, envia os resultados a um operador serialize result.

Uma consulta como a seguinte seria bem-sucedida porque o mesmo conjunto de tipos de dados é usado para cada coluna, mesmo que os filhos usem variáveis diferentes para os nomes das colunas:

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

Uma consulta como a seguinte não seria bem-sucedida porque os filhos usam tipos de dados diferentes para as colunas:

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

Subconsultas escalares

Uma subconsulta escalar é uma subexpressão SQL que faz parte de uma expressão escalar. O Cloud Spanner tenta remover as subconsultas escalares sempre que possível. Em determinadas situações, no entanto, os planos podem conter explicitamente subconsultas escalares.

Por exemplo, para esta consulta:

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

Esta é a subexpressão SQL:

SELECT COUNT(*)
FROM Songs
WHERE Duration > 300

Os resultados da consulta completa são os seguintes:

FirstName
Alice 1
Catalina 0
David 0
Lea 0
Marc 0

Este é o plano de execução:

operador scalar subquery

O plano de execução contém uma subconsulta escalar, mostrada como Scalar Subquery, acima de um operador aggregate.

O Cloud Spanner às vezes converte subconsultas escalares em outro operador, como "join" ou "cross apply", para talvez melhorar o desempenho.

Por exemplo, para esta consulta:

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

Esta é a subexpressão SQL:

SELECT MAX(Duration) FROM Songs

Os resultados da consulta completa são os seguintes:

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

Este é o plano de execução:

operador scalar subquery não aparece no plano

O plano de execução não contém uma subconsulta escalar porque o Cloud Spanner converteu a subconsulta escalar em "cross apply".

Subconsultas de matriz

Uma subconsulta de matriz é semelhante a uma subconsulta escalar, exceto que a subconsulta pode consumir mais de uma linha de entrada. As linhas consumidas são convertidas em uma única matriz de saída escalar que contém um elemento por linha de entrada consumida.

Por exemplo, para esta consulta:

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

Esta é a subconsulta:

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

Os resultados da subconsulta de cada AlbumId são convertidos em uma matriz de linhas ConcertDate comparadas ao AlbumId. O plano de execução contém uma subconsulta de matriz, mostrada como Array Subquery, acima de um operador "distributed union":

operador array subquery

Operadores distribuídos

Os operadores descritos anteriormente nesta página são executados dentro dos limites de uma única máquina. Operadores distribuídos são executados em vários servidores.

Os operadores a seguir são distribuídos:

O operador "distributed union" é o operador primitivo do qual se derivam o "distributed cross apply" e o "distributed outer apply".

Os operadores distribuídos aparecem em planos de execução com uma variante de distributed union acima de uma ou mais variantes de local distributed union. Uma variante de "distributed union" executa a distribuição remota de subplanos. Uma variante de "local distributed union" está acima de cada uma das verificações executadas para a consulta, conforme mostrado neste plano de execução:

operador distribuído

As variantes de "local distributed union" asseguram a execução estável da consulta quando ocorrem reinicializações para alterar dinamicamente os limites de divisão.

Sempre que possível, uma variante de "distributed union" tem um predicado de divisão que resulta em um corte da divisão, o que significa que os servidores remotos só executam subplanos nas divisões que satisfazem ao predicado. Isso melhora a latência e o desempenho geral da consulta.

Distributed union

Com um operador distributed union, é possível separar conceitualmente uma ou mais tabelas em várias divisões, avaliar remotamente uma subconsulta de modo independente em cada divisão e, em seguida, unir todos os resultados.

Por exemplo, para esta consulta:

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

Estes são os resultados:

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

Este é o plano de execução:

operador distributed union

Com o operador "distributed union", é possível enviar subplanos aos servidores remotos que executam uma operação table scan nas divisões que atendem ao predicado WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK'. O operador serialize result faz o cálculo dos valores de SongName e SongGenre das linhas retornadas pelas verificações de tabela. Em seguida, o operador "distributed union" retorna os resultados combinados dos servidores remotos como resultados da consulta SQL.

Distributed cross apply

O operador distributed cross apply (DCA) estende o operador cross apply por meio da execução em vários servidores. O lado "input" do DCA agrupa lotes de linhas, ao contrário de um operador "cross apply" regular, que atua em apenas uma linha "input" por vez. O lado "map" do DCA é um conjunto de operadores "cross apply" que é executado em servidores remotos.

Por exemplo, para esta consulta:

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

Os resultados vêm no formato:

AlbumTitle
Green
Nothing To Do With Me
Play
Total Junk
Green

Este é o plano de execução:

operador distributed cross apply

Na entrada de DCA, há uma operação index scan na tabela Albums que reúne as linhas dos dados AlbumId e SingerId. O lado "map" desse operador "cross apply" é uma operação "index scan" no índice SongsBySingerAlbumSongNameDesc, sujeito ao predicado de SingerId na linha "input" que corresponde à chave SingerId no índice SongsBySingerAlbumSongNameDesc. O mapeamento retorna o SongName referente aos valores de SingerId nas linhas de entrada em lote.

Para resumir o processo de DCA deste exemplo, a entrada do DCA são as linhas reunidas em lote da tabela Albums, e a saída do DCA é a aplicação dessas linhas ao mapa da verificação de índice.

Distributed outer apply

O operador distributed outer apply estende o operador outer apply por meio da execução em vários servidores, semelhante ao modo em que um operador "distributed cross apply" estende um operador "cross apply".

Por exemplo, para esta consulta:

SELECT AlbumTitle FROM Songs
LEFT OUTER JOIN@{JOIN_TYPE=APPLY_JOIN} Albums
ON Albums.AlbumId=Songs.AlbumId

Os resultados vêm no formato:

AlbumTitle
Green
Nothing To Do With Me
Play
Total Junk
Green

Este é o plano de execução:

operador distributed outer apply

Informações adicionais

Esta seção contém os itens que não são operadores autônomos, mas que executam tarefas para aceitar um ou mais dos operadores listados acima. Os itens descritos aqui são tecnicamente operadores, mas não são operadores separados no plano de consulta.

Construtor de estrutura

Um construtor de estrutura cria uma estrutura ou uma coleção de campos. Geralmente, cria uma estrutura para linhas resultantes de uma operação de computação. Um construtor de estrutura não é um operador autônomo. Em vez disso, ele é exibido em operadores compute struct ou serialize result.

Para uma operação "compute struct", o construtor de estrutura cria uma estrutura para que as colunas das linhas computadas possam usar uma única referência de variável para a estrutura.

Para uma operação "serialize result", o construtor de estrutura cria uma estrutura para serializar os resultados.

Por exemplo, para esta consulta:

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

Estes são os resultados:

A
1

Este é o plano de execução:

construtor de estrutura

No plano de execução, os construtores de estrutura aparecem dentro de um operador "serialize result".

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Cloud Spanner