쿼리 실행 연산자

소개

이 페이지에서는 Cloud Spanner 쿼리 실행 계획에 사용되는 연산자를 자세히 설명합니다. Cloud Console을 사용하여 특정 쿼리의 실행 계획을 검색하는 방법에 대해서는 Cloud Spanner의 쿼리 실행 방법 이해를 참조하세요.

이 페이지의 쿼리 및 실행 계획은 다음 데이터베이스 스키마를 기반으로 합니다.

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

다음과 같은 데이터 조작 언어(DML) 문을 사용하여 이러한 테이블에 데이터를 추가할 수 있습니다.

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

Leaf 연산자

Leaf 연산자는 하위 요소가 없는 연산자입니다. Leaf 연산자 유형은 다음과 같습니다.

배열 중첩 해제

배열 중첩 해제 연산자는 입력 배열을 요소 행으로 평면화합니다. 각 결과 행에는 배열의 실제 값과 0부터 시작하는 배열 내 위치(선택사항)가 들어 있는 최대 2개의 열이 포함됩니다.

예를 들어 다음 쿼리를 사용합니다.

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

이 쿼리는 a 열에 있는 [1,2,3] 배열을 평면화하고 b 열에 배열 위치를 표시합니다.

결과는 다음과 같습니다.

a b
1 0
2 1
3 2

다음은 실행 계획입니다.

배열 중첩 해제 연산자

관계 생성

관계 생성 연산자는 0개 이상의 행을 반환합니다.

단위 관계

단위 관계는 1개의 행을 반환합니다. 이것은 관계 생성 연산자의 특별한 경우입니다.

예를 들어 다음 쿼리를 사용합니다.

SELECT 1 + 2 AS Result;

결과는 다음과 같습니다.

결과
3

다음은 실행 계획입니다.

단위 관계 연산자

빈 관계

빈 관계는 행을 반환하지 않습니다. 이것은 관계 생성 연산자의 특별한 경우입니다.

예를 들어 다음 쿼리를 사용합니다.

SELECT * FROM Albums LIMIT 0

결과는 다음과 같습니다.

No results

다음은 실행 계획입니다.

빈 관계 연산자

스캔

스캔 연산자는 행 소스를 스캔하여 행을 반환합니다. 다음은 스캔 연산자의 유형입니다.

  • 테이블 스캔: 테이블에서 스캔이 실행됩니다.
  • 색인 스캔: 색인에서 스캔이 실행됩니다.
  • 배치 스캔: 다른 관계형 연산자에서 생성된 중간 테이블(예: 분산 교차 적용에서 생성된 테이블)에서 스캔이 실행됩니다.

가능할 때마다 Cloud Spanner는 스캔의 일부로 키에 간단한 조건자를 적용합니다. 조건자가 적용되면 스캔 시 전체 테이블 또는 색인을 읽을 필요가 없으므로 스캔이 보다 효율적으로 실행됩니다. 조건자는 실행 계획에 KeyPredicate: column=value 형식으로 나타납니다.

최악의 경우에는 쿼리가 테이블에 있는 행을 모두 조회해야 할 수 있습니다. 이러한 상황은 전체 스캔으로 이어지고, 실행 계획에 full scan: true로 표시됩니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

LastName
Smith

다음은 실행 계획입니다.

스캔 연산자

실행 계획에서 최상위 수준의 분산 통합 연산자는 원격 서버로 하위 계획을 보냅니다. 각 하위 계획에는 결과 직렬화 연산자와 색인 스캔 연산자가 있습니다. 조건자 Key Predicate: FirstName = 'Catalina'는 색인 SingersByFirstLastname에서 FirstNameCatalina인 행으로 스캔을 제한합니다. 색인 스캔 출력은 결과 직렬화 연산자로 반환됩니다.

단항 연산자

단항 연산자는 하나의 관계형 하위 요소가 있는 연산자입니다.

다음 연산자들이 단항 연산자입니다.

집계

집계 연산자는 GROUP BY SQL 문과 집계 함수(예: COUNT)를 실행합니다. 집계 연산자의 입력은 키 열에 정렬된 그룹(또는 GROUP BY가 없는 경우 단일 그룹)으로 논리적으로 분할됩니다. 각 그룹에 대해 0개 이상의 집계가 계산됩니다.

예를 들어 다음 쿼리를 사용합니다.

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

이 쿼리는 SingerId를 기준으로 그룹화를 수행한 후 AVG 집계와 COUNT 집계를 수행합니다.

결과는 다음과 같습니다.

SingerId 평균
3 278 1
2 225.875 8

다음은 실행 계획입니다.

집계 연산자

집계 연산자는 스트림 기반 또는 해시 기반일 수 있습니다. 위의 실행 계획은 스트림 기반 집계를 보여줍니다. 스트림 기반 집계는 이미 사전 정렬된 입력을 읽고(GROUP BY가 있는 경우) 차단 없이 그룹을 컴퓨팅합니다. 해시 기반 집계는 여러 입력 행의 증분 집계를 동시에 유지하기 위해 해시 테이블을 작성합니다. 스트림 기반 집계는 해시 기반 집계보다 메모리를 적게 사용하고 빠르지만 입력을 정렬해야 합니다(키 열 또는 보조 색인 사용).

분산 시나리오의 경우, 집계 연산자를 로컬/전역 쌍으로 분리할 수 ​​있습니다. 각 원격 서버는 입력 행에서 로컬 집계를 수행한 후 결과를 루트 서버로 반환합니다. 루트 서버는 전역 집계를 수행합니다.

변형 적용

변형 적용 연산자는 데이터 조작 언어(DML) 문의 변형을 테이블에 적용합니다. 이것은 DML 문의 쿼리 계획에서 최상위 연산자입니다.

예를 들어 다음 쿼리를 사용합니다.

DELETE FROM Singers
WHERE FirstName = 'Alice';

결과는 다음과 같습니다.

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

다음은 실행 계획입니다.

변형 적용 연산자

배치 만들기

배치 만들기 연산자는 입력 행을 하나의 시퀀스로 일괄 처리합니다. 배치 만들기 연산은 일반적으로 분산 교차 적용 연산의 일부로 수행됩니다. 입력 행은 일괄 처리 중에 다시 정렬될 수 있습니다. 일괄 연산자를 실행할 때마다 일괄 처리되는 입력 행 수는 달라집니다.

실행 계획에서 배치 만들기 연산자의 예시를 보려면 분산 교차 적용 연산자를 참조하세요.

컴퓨팅

컴퓨팅 연산자는 입력 행을 읽고 스칼라 표현식을 통해 계산된 추가 열을 1개 이상 추가하여 출력을 생성합니다. 실행 계획에서 컴퓨팅 연산자의 예시를 보려면 전체 통합 연산자를 참조하세요.

컴퓨팅 구조체

컴퓨팅 구조체 연산자는 각 입력 열의 필드가 있는 구조체 변수를 만듭니다.

예를 들어 다음 쿼리를 사용합니다.

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;

결과는 다음과 같습니다.

FirstName 미지정
Alice [["Not About The Guitar","BLUES"]]

다음은 실행 계획입니다.

컴퓨팅 구조체 연산자

실행 계획에서 배열 서브 쿼리 연산자는 분산 통합 연산자로부터 입력을 받으며 분산 통합 연산자는 컴퓨팅 구조체 연산자로부터 입력을 받습니다. 컴퓨팅 구조체 연산자는 Songs 테이블의 SongNameSongGenre 열에서 구조체를 만듭니다.

필터

필터 연산자는 입력에서 모든 행을 읽고 각 행에서 스칼라 조건자를 적용한 후 이 조건자를 충족하는 행만 반환합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

LastName
Richards

다음은 실행 계획입니다.

필터 연산자

성이 Rich로 시작하는 가수에 대한 조건자가 필터로 구현됩니다. 이 필터의 입력은 색인 스캔의 출력이고, 필터 출력은 LastNameRich로 시작하는 행입니다.

성능을 위해 필터가 스캔 위에 직접 위치할 때마다 필터는 데이터가 판독되는 방식에 영향을 줍니다. 예를 들어 키 k가 있는 테이블을 생각해보겠습니다. 테이블의 스캔 바로 위에 조건자 k = 5가 있는 필터는 전체 입력을 읽지 않고 k = 5와 일치하는 행을 찾습니다. 이렇게 하면 쿼리가 보다 효율적으로 실행됩니다. 위의 예시에서 필터 연산자는 WHERE s.LastName LIKE 'Rich%' 조건자를 충족하는 행만 읽습니다.

필터 스캔

필터 스캔 연산자는 항상 테이블 또는 색인 스캔의 맨 위에 있습니다. 이 연산자는 스캔을 사용하여 데이터베이스에서 읽은 행의 수를 줄이기 때문에 일반적으로 필터를 사용하는 경우보다 스캔이 더 빠릅니다. Cloud Spanner는 특정 조건에서 필터 스캔을 적용합니다.

  • 검색 가능한 조건: 검색 가능한 조건은 Cloud Spanner가 테이블에서 액세스할 특정 행을 결정할 수 있는 경우에 적용됩니다. 일반적으로는 필터가 기본 키의 프리픽스에 있는 경우가 이에 해당합니다. 예를 들어 기본 키가 Col1Col2로 구성된 경우, Col1, 또는 Col1Col2의 명시적 값을 포함하는 WHERE 절은 검색 가능합니다. 이 경우 Cloud Spanner는 키 범위 내에서만 데이터를 읽습니다.
  • 잔여 조건: 읽는 데이터의 양을 제한하기 위해 Cloud Spanner가 스캔을 평가할 수 있는 그 밖의 모든 조건입니다.

예를 들어 다음 쿼리를 사용합니다.

SELECT LastName
FROM Singers
WHERE SingerId = 1

결과는 다음과 같습니다.

LastName
Richards

다음은 실행 계획입니다.

필터 스캔 연산자

제한

제한 연산자는 반환되는 행 수를 제한합니다. 선택사항인 OFFSET 매개변수는 반환할 시작 행을 지정합니다. 분산 시나리오의 경우, 제한 연산자를 로컬/전역 쌍으로 분리할 수 있습니다. 각 원격 서버는 출력 행에 대해 로컬 제한을 적용한 후 결과를 루트 서버에 반환합니다. 루트 서버는 원격 서버가 보낸 행을 집계한 후 전역 제한을 적용합니다.

예를 들어 다음 쿼리를 사용합니다.

SELECT s.SongName
FROM Songs AS s
LIMIT 3;

결과는 다음과 같습니다.

SongName
Not About The Guitar
The Second Time
Starting Again

다음은 실행 계획입니다.

제한 연산자

로컬 제한은 각 원격 서버에 대한 제한입니다. 루트 서버는 원격 서버의 행을 집계한 후 전역 제한을 적용합니다.

샘플

샘플 연산자는 입력 행의 샘플링에 따라 입력 하위 집합을 반환합니다. 지원되는 샘플링 방법으로는 BernoulliReservoir가 있습니다.

예를 들어 다음 쿼리를 사용합니다.

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

쿼리는 10%의 샘플링 레이트로 Bernoulli 샘플링을 사용합니다.

결과는 다음과 같습니다.

SongName
Starting Again
Nothing Is The Same

결과는 샘플이므로 쿼리가 동일해도 쿼리를 실행할 때마다 결과가 달라질 수 있습니다.

다음은 실행 계획입니다.

샘플 연산자

이 실행 계획에서 샘플 연산자는 분산 통합 연산자로부터 입력을 받으며 분산 통합 연산자는 색인 스캔 연산자로부터 입력을 받습니다. 샘플 연산자는 샘플 행을 결과 직렬화 연산자로 반환합니다.

결과 직렬화

결과 직렬화 연산자는 클라이언트에 반환하기 위해 쿼리의 최종 결과에 있는 각 행을 직렬화하는 컴퓨팅 구조체 연산자의 특수한 경우입니다.

예를 들어 다음 쿼리를 사용합니다.

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

이 쿼리는 SingerId를 기준으로 SongNameSongGenre로 구성된 배열을 요청합니다.

결과는 다음과 같습니다.

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

다음은 실행 계획입니다.

결과 직렬화 연산자

결과 직렬화 연산자는 Singers 테이블의 각 행에 대해 가수의 곡에 대한 SongNameSongGenre 쌍의 배열을 포함하는 결과를 만듭니다.

정렬

정렬 연산자는 입력 행을 읽고 열을 기준으로 이를 정렬한 후 정렬된 결과를 반환합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

SongGenre
BLUES
BLUES
BLUES
BLUES
CLASSICAL
COUNTRY
ROCK
ROCK
ROCK

다음은 실행 계획입니다.

정렬 연산자

이 실행 계획에서 정렬 연산자는 분산 통합 연산자로부터 입력 행을 받아 입력 행을 정렬하고 정렬된 행을 결과 직렬화 연산자로 반환합니다.

반환되는 행 수를 제한하기 위해 정렬 연산자는 선택적으로 LIMITOFFSET 매개변수를 사용할 수 있습니다. 분산 시나리오의 경우, LIMIT 또는 OFFSET 연산자가 있는 정렬 연산자는 로컬/전역 쌍으로 분리됩니다. 각 원격 서버는 입력 행에 대한 정렬 순서와 로컬 제한/오프셋을 적용한 후 결과를 루트 서버에 반환합니다. 루트 서버는 원격 서버가 보낸 행을 집계하고 정렬한 후 전역 제한/오프셋을 적용합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

SongGenre
BLUES
BLUES
BLUES

다음은 실행 계획입니다.

제한이 있는 정렬 연산자

실행 계획에는 원격 서버에 대한 로컬 제한과 루트 서버에 대한 전역 제한이 표시됩니다.

통합 입력

통합 입력 연산자는 결과를 전체 통합 연산자로 반환합니다. 실행 계획에서 통합 입력 연산자의 예시를 보려면 전체 통합 연산자를 참조하세요.

바이너리 연산자

바이너리 연산자는 2개의 관계형 하위 요소가 있는 연산자입니다. 다음 연산자는 바이너리 연산자입니다.

교차 적용

교차 적용 연산자는 다른 테이블의 쿼리로 검색된 각 행에 대해 테이블 쿼리를 실행하고 모든 테이블 쿼리 실행 결과를 통합해서 반환합니다. 교차 적용 및 외부 적용 연산자는 해시 조인처럼 집합 기반 처리를 실행하는 연산자와는 달리 행 기반 처리를 실행합니다. 교차 적용 연산자에는 입력 등 2가지 입력이 있습니다. 교차 적용 연산자는 입력 측의 각 행을 맵 측에 적용합니다. 교차 적용 결과에는 입력 및 맵 측 모두의 열이 있습니다.

예를 들어 다음 쿼리를 사용합니다.

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

쿼리는 각 가수의 성과 가수의 곡 중 한 곡 이름만 요청합니다.

결과는 다음과 같습니다.

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

첫 번째 열에는 Singers 테이블의 내용이 채워지고 두 번째 열에는 Songs 테이블의 내용이 채워집니다. Singers 테이블에 SingerId 1개가 있지만 Songs 테이블에 일치하는 SingerId가 없으면 두 번째 열에 NULL이 포함됩니다.

다음은 실행 계획입니다.

교차 적용 연산자

최상위 노드는 분산 통합 연산자입니다. 분산 통합 연산자는 원격 서버에 하위 계획을 분배합니다. 이 하위 계획에는 가수의 성과 발표곡 중 한 곡의 이름을 컴퓨팅하고 출력의 각 행을 직렬화하는 결과 직렬화 연산자가 포함되어 있습니다.

결과 직렬화 연산자는 교차 적용 연산자에서 입력을 받습니다. 교차 적용 연산자의 입력 측은 Singers 테이블에 대한 테이블 스캔입니다.

교차 적용 연산의 맵 측에는 다음이 포함됩니다(위에서 아래로).

  • Songs.SongName을 반환하는 집계 연산자
  • 가수 1명당 반환되는 곡 수를 제한하는 제한 연산자
  • SongsBySingerAlbumSongNameDesc 색인에 대한 색인 스캔

교차 적용 연산자는 입력 측의 각 행을 동일한 SingerId를 가진 맵 측의 행에 매핑합니다. 교차 적용 연산자 출력은 입력 행의 FirstName 값과 맵 행의 SongName 값입니다. SingerId에 일치하는 맵 행이 없으면 SongName 값은 NULL이 됩니다. 그런 다음 실행 계획 맨 위에 있는 분산 통합 연산자가 원격 서버의 모든 출력 행을 결합하여 쿼리 결과로 반환합니다.

해시 조인

해시 조인 연산자는 해시에 기반해 SQL 조인을 구현한 것입니다. 해시 조인은 집합 기반 프로세싱을 실행합니다. 해시 조인 연산자는 빌드로 표시된 입력에서 행을 읽고 이를 조인 조건에 따라 해시 테이블에 삽입합니다. 그런 다음 해시 조인 연산자는 프로브로 표시된 입력에서 행을 읽습니다. 프로브 입력에서 읽는 각 행에 대해 해시 조인 연산자는 해시 테이블에서 일치하는 행을 찾습니다. 해시 조인 연산자는 일치하는 행을 결과로 반환합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

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's Get Back Together
Green I Knew You Were Magic
Green Blue
Green 42
Terrified Fight Story

다음은 실행 계획입니다.

해시 조인 연산자

실행 계획에서 빌드Albums 테이블에 대한 스캔을 분산하는 분산 통합입니다. 프로브SongsBySingerAlbumSongNameDesc 색인에 대한 스캔을 분산하는 분산 통합 연산자입니다. 해시 조인 연산자는 빌드 측의 모든 행을 읽습니다. 각 빌드 행은 조건 a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId의 열을 기반으로 해시 테이블에 배치됩니다. 그런 다음 해시 조인 연산자는 프로브 측의 모든 행을 읽습니다. 각 스캔 행에 대해 해시 조인 연산자는 해시 테이블에서 일치하는 항목을 찾습니다. 일치 항목은 해시 조인 연산자에 의해 반환됩니다.

해시 테이블에서의 일치 결과는 반환되기 전에 나머지 조건으로 필터링될 수도 있습니다. (나머지 조건이 나타나는 부분의 예는 비동등 조인에 있습니다.) 해시 조인 실행 계획은 메모리 관리 및 조인 변형으로 인해 복잡할 수 있습니다. 메인 해시 조인 알고리즘은 내부, 반, 반대, 외부 조인 변형을 처리하도록 조정됩니다.

외부 적용

외부 적용 연산자는 필요할 경우 NULL로 채워진 행을 작성하여 맵 측의 각 실행이 행을 1개 이상 반환하도록 한다는 점만 제외하고는 교차 적용 연산자와 유사합니다. (즉, 왼쪽 외부 조인 의미를 제공합니다.)

N-항 연산자

N-항 연산자는 관계형 하위 요소가 2개 이상 있는 연산자입니다. 다음 연산자가 N-항 연산자입니다.

전체 통합

전체 통합 연산자는 중복을 제거하지 않고 하위 요소의 모든 행 집합을 결합합니다. 전체 통합 연산자는 여러 서버에 분산된 통합 입력 연산자로부터 입력을 받습니다. 전체 통합 연산자에는 동일한 스키마를 갖는 입력이 필요합니다. 즉, 각 열에 대해 동일한 데이터 유형 집합이 필요합니다.

예를 들어 다음 쿼리를 사용합니다.

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

하위 요소의 행 유형은 정수 2개로 구성됩니다.

결과는 다음과 같습니다.

a b
1 2
3 4
5 6

다음은 실행 계획입니다.

union_all_operator

전체 통합 연산자는 입력 행을 결합하며, 이 예시에서는 결과를 결과 직렬화 연산자로 보냅니다.

하위 요소가 열 이름에 대해 다른 변수를 사용하더라도 각 열에 동일한 데이터 유형 집합이 사용되므로, 다음과 같은 쿼리가 성공합니다.

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

하위 요소가 열에 다른 데이터 유형을 사용하므로, 다음과 같은 쿼리는 실패합니다.

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

스칼라 서브 쿼리

스칼라 서브 쿼리는 스칼라 표현식의 일부인 SQL 하위 표현식입니다. Cloud Spanner는 가능한 경우 항상 스칼라 서브 쿼리 제거를 시도합니다. 그러나 특정 시나리오에서는 계획에 스칼라 서브 쿼리가 명시적으로 포함될 수 있습니다.

예를 들어 다음 쿼리를 사용합니다.

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

다음은 SQL 하위 표현식입니다.

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

다음은 전체 쿼리 결과입니다.

FirstName
Alice 1
Catalina 0
David 0
Lea 0
Marc 0

다음은 실행 계획입니다.

스칼라 서브 쿼리 연산자

이 실행 계획은 집계 연산자 위에 Scalar Subquery로 표시된 스칼라 서브 쿼리를 포함합니다.

Cloud Spanner는 때로 스칼라 서브 쿼리를 조인 또는 교차 적용과 같은 다른 연산자로 변환하여 성능을 향상시킬 수 있습니다.

예를 들어 다음 쿼리를 사용합니다.

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

다음은 SQL 하위 표현식입니다.

SELECT MAX(Duration) FROM Songs;

다음은 전체 쿼리 결과입니다.

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

다음은 실행 계획입니다.

계획에 표시되지 않는 스칼라 서브 쿼리 연산자

Cloud Spanner가 스칼라 서브 쿼리를 교차 적용으로 변환했으므로, 실행 계획에는 스칼라 서브 쿼리가 포함되지 않습니다.

배열 서브 쿼리

배열 서브 쿼리는 스칼라 서브 쿼리와 비슷하지만 서브 쿼리가 입력 행을 2개 이상 사용할 수 있다는 점이 다릅니다. 소비된 행은 소비된 입력 행당 하나의 요소를 포함하는 단일 스칼라 출력 배열로 변환됩니다.

예를 들어 다음 쿼리를 사용합니다.

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

다음은 서브 쿼리입니다.

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

AlbumId에 대한 서브 쿼리 결과가 해당 AlbumId에 대응한 ConcertDate 행 배열로 변환됩니다. 실행 계획에는 분산 통합 연산자 위에 Array Subquery로 표시된 배열 서브 쿼리가 포함됩니다.

배열 서브 쿼리 연산자

분산 연산자

이전에 이 페이지에서 설명된 연산자는 단일 머신 내에서 실행됩니다. 분산 연산자는 여러 서버에서 실행됩니다.

다음 연산자가 분산 연산자입니다.

분산 통합 연산자는 분산 교차 적용 및 분산 외부 적용을 파생시킨 기본 연산자입니다.

분산 연산자는 1개 이상의 로컬 분산 통합 변형 위에 분산 통합 변형을 사용하여 실행 계획에 나타납니다. 분산 통합 변형은 하위 계획의 원격 배포를 수행합니다. 이 실행 계획에 표시된 것처럼 로컬 분산 통합 변형은 쿼리에 대해 수행된 각 스캔 위에 있습니다.

분산 연산자

로컬 분산 통합 변형은 동적으로 변하는 분할 경계에 대해 재시작이 발생하는 경우 안정적인 쿼리 실행을 보장합니다.

가능한 경우 분산 통합 변형에는 분할 잘라내기를 유발하는 분할 조건자가 있습니다. 즉, 원격 서버는 조건자를 충족하는 분할에만 하위 계획을 실행합니다. 이렇게 하면 지연 시간과 전반적인 쿼리 성능이 향상됩니다.

분산 통합

분산 통합 연산자는 테이블 1개 이상을 개념적으로 여러 분할로 분할하고 각 분할에서 독립적으로 서브 쿼리를 원격 평가한 후 모든 결과를 통합합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

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

다음은 실행 계획입니다.

분산 통합 연산자

분산 통합 연산자는 분할 전체에서 테이블 스캔을 수행하는 원격 서버로 하위 계획을 보냅니다. 이때 분할은 쿼리의 조건자 WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK'을 만족해야 합니다. 결과 직렬화 연산자는 테이블 스캔에서 반환된 행으로부터 SongNameSongGenre 값을 계산합니다. 그런 다음 분산 통합 연산자는 원격 서버에서 결합된 결과를 SQL 쿼리 결과로 반환합니다.

분산 교차 적용

분산 교차 적용(DCA) 연산자는 교차 적용 연산자를 여러 서버에서 실행하여 확장합니다. DCA 입력 측은 행의 배치를 그룹화합니다(한 번에 입력 행 1개에서만 작업을 수행하는 일반 교차 적용 연산자와 다름). DCA 맵 측은 원격 서버에서 실행되는 교차 적용 연산자 조합입니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같은 형식입니다.

AlbumTitle
Green
Nothing To Do With Me
Play
Total Junk
Green

다음은 실행 계획입니다.

분산 교차 적용 연산자

DCA 입력에는 AlbumId의 행을 일괄 처리하는 SongsBySingerAlbumSongNameDesc 색인에 대한 색인 스캔이 포함됩니다. 이 교차 적용 연산자의 맵 측은 AlbumsByAlbumTitle 색인에서 AlbumId 키와 일치하는 입력 행의 AlbumId 조건자를 조건으로 하는 색인 AlbumsByAlbumTitle의 색인 스캔입니다. 이 매핑으로 일괄 처리된 입력 행의 SingerId 값에 대한 SongName이 반환됩니다.

이 예시의 DCA 프로세스를 요약하면 DCA 입력은 Albums 테이블에서 일괄 처리된 행이고 DCA의 출력은 색인 스캔 맵에 이 행을 적용한 것입니다.

분산 외부 적용

분산 교차 적용 연산자가 교차 적용 연산자를 확장하는 것과 마찬가지로 분산 외부 적용 연산자는 외부 적용 연산자를 여러 서버에서 실행하여 확장합니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같은 형식입니다.

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

다음은 실행 계획입니다.

분산 외부 적용 연산자

추가 정보

이 섹션은 독립 실행형 연산자는 아니지만 위에 나열한 연산자를 1개 이상 지원하는 작업을 실행하는 항목에 대해 설명합니다. 여기에 설명된 항목은 기술적으로 연산자이지만 쿼리 계획에서 별도의 연산자로 구분되지 않습니다.

구조체 생성자

구조체 생성자구조체 또는 필드 컬렉션을 만듭니다. 일반적으로 컴퓨팅 연산의 결과인 행에 대한 구조체를 만듭니다. 구조체 생성자는 독립 실행형 연산자가 아닙니다. 대신, 컴퓨팅 구조체 연산자 또는 결과 직렬화 연산자에 나타납니다.

컴퓨팅 구조체 연산의 경우, 구조체 생성자는 계산된 행에 대한 열이 구조체에 대한 단일 변수 참조를 사용할 수 있도록 구조체를 생성합니다.

결과 직렬화 연산의 경우, 구조체 생성자는 결과를 직렬화하는 구조체를 만듭니다.

예를 들어 다음 쿼리를 사용합니다.

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

결과는 다음과 같습니다.

A
1

다음은 실행 계획입니다.

구조체 생성자

실행 계획에서 구조체 생성자는 결과 직렬화 연산자 안에 나타납니다.