EXPLAIN

EXPLAIN

지정한 SQL 문장의 논리적 실행 계획(logical execution plan)을 반환하는 명령이에요. explain plan은 쿼리를 실행하기 위해 Snowflake가 수행할 작업(예: 테이블 스캔과 조인)을 보여줘요.

출처: 문서

본문

구문 (Syntax)

EXPLAIN [ USING { TABULAR | JSON | TEXT } ] <statement>

파라미터

  • statement — explain plan을 원하는 SQL 문장.
  • USING output_format — 선택 절로 출력 형식을 지정해요. 가능한 출력 형식:
    • JSON: JSON 출력은 테이블에 저장하고 쿼리하기 더 쉬워요.
    • TABULAR: 표 형식 출력은 일반적으로 JSON보다 사람이 읽기 쉬워요.
    • TEXT: 포맷된 텍스트 출력은 일반적으로 JSON보다 사람이 읽기 쉬워요.
    • 기본값은 TABULAR.

출력 (Output)

출력은 다음 정보를 포함해요:

Column Description
step 대부분의 쿼리는 단일 단계를 포함하지만 일부는 여러 개의 개별 단계로 실행돼요. 이 열은 작업이 어떤 단계에 속하는지 나타내요.
id 쿼리 계획의 각 작업에 할당된 고유 식별자.
parentOperators 작업의 부모 노드 식별자 배열. 쿼리 프로필에서 부모는 자식 위에 링크로 연결되어 표시돼요.
operation 작업의 이름. 예: Result, Filter, TableScan, Join, CreateTableFromArchiveData.
objects 테이블 스캔 작업이 참조하는 객체의 이름. 예: table, materialized view, secure view, ARCHIVE OF.
alias 참조된 객체의 별칭(쿼리에서 객체에 별칭이 주어졌다면).
expressions 현재 작업과 관련된 표현식 목록(필터, 조인 조건, 프로젝션, 집계 등).
partitionsTotal 참조된 데이터베이스 객체의 총 마이크로 파티션 수.
partitionsAssigned 컴파일 타임 조정(pruning) 후 참조된 객체에서 남은 파티션 수, 즉 쿼리가 스캔할 수 있는 파티션 수.
bytesAssigned partitionsAssigned에 포함된 바이트 수.

사용 메모 (Usage notes)

  • EXPLAIN은 SQL 문장을 컴파일하지만 실행하지 않으므로 실행 중인 웨어하우스가 필요하지 않아요.
  • EXPLAIN 계획은 현재 웨어하우스 크기에 따라 달라질 수 있어요. 현재 웨어하우스 외부에서 EXPLAIN을 실행하면 Snowflake는 XSMALL 웨어하우스의 용량을 기준으로 EXPLAIN 계획을 구성해요.
  • EXPLAIN은 컴퓨팅 크레딧을 소비하지 않지만, 쿼리 컴파일은 다른 메타데이터 작업처럼 Cloud Service 크레딧을 소비해요.
  • 이 명령의 출력을 후처리하려면:
    • 출력을 쿼리할 수 있는 테이블로 취급하는 RESULT_SCAN 함수를 사용할 수 있어요.
    • JSON 형식으로 출력을 생성하고 나중에 분석을 위해 JSON 형식 출력을 테이블에 삽입할 수 있어요. JSON 형식으로 출력을 저장하면 SYSTEM$EXPLAIN_JSON_TO_TEXT 또는 EXPLAIN_JSON 함수를 사용하여 JSON을 더 사람이 읽기 쉬운 형식(표 또는 포맷된 텍스트)으로 변환할 수 있어요.
  • assignedPartitions와 assignedBytes 값은 쿼리 실행의 상한 추정치예요. 조인 조정(pruning) 같은 런타임 최적화는 쿼리 실행 중 스캔되는 파티션과 바이트 수를 줄일 수 있어요.
  • EXPLAIN 계획은 "논리적" explain plan이에요. 수행될 작업과 그 작업들 사이의 논리적 관계를 보여줘요. 계획에서 작업의 실제 실행 순서가 계획이 보여주는 논리적 순서와 반드시 일치하지는 않아요.
  • EXPLAIN 문장의 데이터베이스 객체 중 하나라도 INFORMATION_SCHEMA 객체이면 문장은 EXPLAIN command has insufficient privilege on object <objName> 오류로 실패해요.

예시 (Examples)

이 예시는 두 개의 작은 테이블에 대한 간단한 쿼리의 EXPLAIN 출력을 보여줘요.

테이블을 만들어요:

CREATE TABLE Z1 (ID INTEGER);
CREATE TABLE Z2 (ID INTEGER);
CREATE TABLE Z3 (ID INTEGER);

쿼리의 EXPLAIN 계획을 표 형식으로 생성해요:

EXPLAIN USING TABULAR SELECT Z1.ID, Z2.ID
    FROM Z1, Z2
    WHERE Z2.ID = Z1.ID;
+------+------+-----------------+-------------+------------------------------+-------+--------------------------+-----------------+--------------------+---------------+
| step | id   | parentOperators | operation   | objects                      | alias | expressions              | partitionsTotal | partitionsAssigned | bytesAssigned |
|------+------+-----------------+-------------+------------------------------+-------+--------------------------+-----------------+--------------------+---------------|
| NULL | NULL |            NULL | GlobalStats | NULL                         | NULL  | NULL                     |               2 |                  2 |          1024 |
|    1 |    0 |            NULL | Result      | NULL                         | NULL  | Z1.ID, Z2.ID             |            NULL |               NULL |          NULL |
|    1 |    1 |             [0] | InnerJoin   | NULL                         | NULL  | joinKey: (Z2.ID = Z1.ID) |            NULL |               NULL |          NULL |
|    1 |    2 |             [1] | TableScan   | TESTDB.TEMPORARY_DOC_TEST.Z2 | NULL  | ID                       |               1 |                  1 |           512 |
|    1 |    3 |             [1] | JoinFilter  | NULL                         | NULL  | joinKey: (Z2.ID = Z1.ID) |            NULL |               NULL |          NULL |
|    1 |    4 |             [3] | TableScan   | TESTDB.TEMPORARY_DOC_TEST.Z1 | NULL  | ID                       |               1 |                  1 |           512 |
+------+------+-----------------+-------------+------------------------------+-------+--------------------------+-----------------+--------------------+---------------+

쿼리의 EXPLAIN 계획을 포맷된 텍스트로 생성해요:

EXPLAIN USING TEXT SELECT Z1.ID, Z2.ID
    FROM Z1, Z2
    WHERE Z2.ID = Z1.ID;
+------------------------------------------------------------------------------------------------------------------------------------+
| content                                                                                                                            |
|------------------------------------------------------------------------------------------------------------------------------------|
| GlobalStats:                                                                                                                       |
|     partitionsTotal=2                                                                                                              |
|     partitionsAssigned=2                                                                                                           |
|     bytesAssigned=1024                                                                                                             |
| Operations:                                                                                                                        |
| 1:0     ->Result  Z1.ID, Z2.ID                                                                                                     |
| 1:1          ->InnerJoin  joinKey: (Z2.ID = Z1.ID)                                                                                 |
| 1:2               ->TableScan  TESTDB.TEMPORARY_DOC_TEST.Z2  ID  {partitionsTotal=1, partitionsAssigned=1, bytesAssigned=512}      |
| 1:3               ->JoinFilter  joinKey: (Z2.ID = Z1.ID)                                                                           |
| 1:4                    ->TableScan  TESTDB.TEMPORARY_DOC_TEST.Z1  ID  {partitionsTotal=1, partitionsAssigned=1, bytesAssigned=512} |
|                                                                                                                                    |
+------------------------------------------------------------------------------------------------------------------------------------+

쿼리의 EXPLAIN 계획을 JSON으로 생성해요:

EXPLAIN USING JSON SELECT Z1.ID, Z2.ID
    FROM Z1, Z2
    WHERE Z2.ID = Z1.ID;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| content                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| {"GlobalStats":{"partitionsTotal":2,"partitionsAssigned":2,"bytesAssigned":1024},"Operations":[[{"id":0,"operation":"Result","expressions":["Z1.ID","Z2.ID"]},{"id":1,"parentOperators":[0],"operation":"InnerJoin","expressions":["joinKey: (Z2.ID = Z1.ID)"]},{"id":2,"parentOperators":[1],"operation":"TableScan","objects":["TESTDB.TEMPORARY_DOC_TEST.Z2"],"expressions":["ID"],"partitionsAssigned":1,"partitionsTotal":1,"bytesAssigned":512},{"id":3,"parentOperators":[1],"operation":"JoinFilter","expressions":["joinKey: (Z2.ID = Z1.ID)"]},{"id":4,"parentOperators":[3],"operation":"TableScan","objects":["TESTDB.TEMPORARY_DOC_TEST.Z1"],"expressions":["ID"],"partitionsAssigned":1,"partitionsTotal":1,"bytesAssigned":512}]]} |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

더 알아보기 (Learn more)