본문으로 건너뛰기
최종 수정: 에

EXPLAIN

설명​

EXPLAIN 문은 주어진 쿼리에 대한 Doris의 쿼리 실행 계획을 표시합니다. Doris의 쿼리 옵티마이저는 통계 데이터, 데이터 특성, HASH JOIN, 파티셔닝, 버키팅 등의 기능을 활용하여 효율적인 계획을 생성하는 것을 목표로 합니다. 그러나 이론적·실무적 제약으로 인해 계획의 성능이 기대에 미치지 못할 때도 있습니다.

성능을 개선하려면 현재 계획을 분석해야 합니다. 이 문서에서는 EXPLAIN 문을 사용하여 최적화하는 방법을 설명합니다.

구문​

{EXPLAIN | DESC} [VERBOSE] <query_block>

필수 매개변수​

<query_block>

실행 계획을 확인하려는 쿼리 문입니다.

선택적 매개변수​

[VERBOSE]

상세 정보의 표시 여부는 VERBOSE 지정 여부에 따라 결정됩니다. VERBOSE를 지정하면 각 연산자의 세부 정보, 사용하는 튜플 ID, 각 튜플에 대한 상세 설명 등 포괄적인 정보가 표시됩니다. 지정하지 않으면 간략한 정보가 제공됩니다.

반환 결과​

기본 개념​

EXPLAIN이 표시하는 정보를 더 잘 이해할 수 있도록 Doris 실행 계획의 핵심 개념 몇 가지를 소개합니다.

이름설명
PLAN실행 계획입니다. 실행 계획기가 쿼리를 실행 계획으로 변환하면 실행 엔진이 이를 실행합니다.
FRAGMENT실행 프래그먼트입니다. Doris는 분산 실행 엔진이므로 전체 실행 계획을 여러 단일 노드 실행 프래그먼트로 나눕니다. FRAGMENT 테이블은 하나의 완전한 단일 노드 실행 프래그먼트를 나타냅니다. 여러 FRAGMENT가 결합하여 하나의 완전한 PLAN을 구성합니다.
PLAN NODE연산자입니다. 실행 계획의 가장 작은 단위입니다. FRAGMENT는 여러 연산자로 구성됩니다. 각 연산자는 집계, 조인 등 특정 실행 로직을 담당합니다.

반환 결과 구조​

Doris EXPLAIN 문의 결과는 하나의 완전한 PLAN입니다. PLAN 내에서 FRAGMENT는 실행 순서의 역순으로 배치됩니다. 각 FRAGMENT 내에서도 연산자(PLAN NODE)는 실행 순서의 역순으로 배치됩니다.

아래는 예시입니다.

+--------------------------------------------------+
| Explain String(Nereids Planner) |
+--------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS: |
| cnt[#10] |
| cnt[#11] |
| PARTITION: UNPARTITIONED |
| |
| HAS_COLO_PLAN_NODE: false |
| |
| VRESULT SINK |
| MYSQL_PROTOCAL |
| |
| 7:VEXCHANGE |
| offset: 0 |
| distribute expr lists: |
| |
| PLAN FRAGMENT 1 |
| |
| PARTITION: RANDOM |
| |
| HAS_COLO_PLAN_NODE: false |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 07 |
| UNPARTITIONED |
| |
| 6:VHASH JOIN(354) |
| | join op: INNER JOIN(BROADCAST)[] |
| | equal join conjunct: cnt[#7] = cnt[#5] |
| | cardinality=1 |
| | vec output tuple id: 8 |
| | vIntermediate tuple ids: 7 |
| | hash output slot ids: 5 7 |
| | distribute expr lists: |
| | distribute expr lists: |
| | |
| |----4:VEXCHANGE |
| | offset: 0 |
| | distribute expr lists: |
| | |
| 5:VEXCHANGE |
| offset: 0 |
| distribute expr lists: |
| |
| PLAN FRAGMENT 2 |
| ... |
| |
| PLAN FRAGMENT 3 |
| ... |
+--------------------------------------------------+

연산자는 점선으로 자식 노드에 연결됩니다. 연산자에 자식이 여러 개 있으면 세로로 배치되며, 이는 오른쪽에서 왼쪽으로의 순서를 나타냅니다. 위 예시에서 연산자 6(VHASH JOIN)의 왼쪽 자식은 연산자 5(EXCHANGE)이고 오른쪽 자식은 연산자 4(EXCHANGE)입니다.

Fragment 필드 설명​

이름설명
PARTITION현재 Fragment의 데이터 분포를 표시합니다.
HAS_COLO_PLAN_NODEFragment에 colocate 연산자가 포함되어 있는지 나타냅니다.
SinkFragment의 데이터 출력 방식입니다. 자세한 내용은 아래 표를 참조하세요.

Sink 방식

이름설명
STREAM DATA SINK데이터를 다음 Fragment로 출력합니다. 두 줄의 정보가 포함됩니다.
첫 번째 줄: 데이터를 전송할 다운스트림 EXCHANGE NODE입니다.
두 번째 줄: 데이터 분산 방식입니다.
- UNPARTITIONED는 각 다운스트림 인스턴스가 전체 데이터 집합을 수신함을 의미합니다. 일반적으로 브로드캐스트 조인이나 전역 limit 또는 order by처럼 단일 인스턴스 로직이 필요한 경우에 사용됩니다.
- RANDOM은 각 다운스트림 인스턴스가 중복 없이 무작위 데이터 부분집합을 수신함을 의미합니다.
- HASH_PARTITIONED는 나열된 슬롯을 키로 해싱하여 데이터 샤드를 동일한 다운스트림 인스턴스로 전송합니다. 주로 파티션 해시 조인의 업스트림이나 두 단계 집계의 두 번째 단계에서 사용됩니다.
RESULT SINK결과 데이터를 FE로 전송합니다. 첫 번째 줄은 데이터 전송에 사용되는 프로토콜을 나타내며, 현재 MySQL 및 arrow 프로토콜을 지원합니다.
OLAP TABLE SINK데이터를 OLAP 테이블에 씁니다.
MultiCastDataSinks여러 STREAM DATA SINK를 포함하는 멀티캐스트 연산자입니다. 각 STREAM DATA SINK는 전체 데이터 집합을 해당 다운스트림으로 전송합니다.

튜플 정보 설명​

VERBOSE 모드를 사용하면 튜플 정보가 출력됩니다. 튜플 정보는 데이터 행 내의 SLOT 세부 정보를 설명하며, SLOT 유형, null 허용 여부 등을 포함합니다.

출력에는 여러 TupleDescriptor가 포함되며, 각 TupleDescriptor는 여러 SlotDescriptor를 포함합니다. 아래는 예시입니다.

Tuples:
TupleDescriptor{id=0, tbl=t1}
SlotDescriptor{id=0, col=c1, colUniqueId=0, type=int, nullable=true, isAutoIncrement=false, subColPath=null}
SlotDescriptor{id=2, col=c3, colUniqueId=2, type=int, nullable=true, isAutoIncrement=false, subColPath=null}

TupleDescriptor​

이름설명
id튜플 디스크립터의 ID입니다.
tbl튜플에 해당하는 테이블이며, 해당 사항이 없으면 null입니다.

SlotDescriptor​

이름설명
id슬롯 디스크립터의 ID입니다.
col슬롯에 해당하는 컬럼이며, 해당 사항이 없으면 비어 있습니다.
colUniqueId해당 컬럼의 고유 ID이며, 해당 사항이 없으면 -1입니다.
type슬롯의 유형입니다.
nullable해당 데이터가 null일 수 있는지 나타냅니다.
isAutoIncrement컬럼이 자동 증가하는지 나타냅니다.
subColPath컬럼 내 하위 컬럼의 경로이며, 현재는 variant 유형에만 적용됩니다.

연산자 설명​

연산자 목록​

이름설명
AGGREGATE집계 연산자
ANALYTIC윈도우 함수 연산자
ASSERT NUMBER OF ROWS다운스트림 출력 행 수를 검사하는 연산자
EXCHANGE데이터 교환 수신 연산자
MERGING-EXCHANGE정렬 및 행 수 제한 기능을 갖춘 데이터 교환 수신 연산자
HASH JOIN해시 조인 연산자
NESTED LOOP JOIN중첩 루프 조인 연산자
PartitionTopN파티션 내 데이터 사전 필터링 연산자
REPEAT_NODE데이터 복제 연산자
DataGenScanNode테이블 반환 함수 연산자
EsScanNodeES 테이블 스캔 연산자
HIVE_SCAN_NODEHive 테이블 스캔 연산자
HUDI_SCAN_NODEHudi 테이블 스캔 연산자
ICEBERG_SCAN_NODEIceberg 테이블 스캔 연산자
PAIMON_SCAN_NODEPaimon 테이블 스캔 연산자
JdbcScanNodeJdbc 테이블 스캔 연산자
OlapScanNodeOlap 테이블 스캔 연산자
SELECT필터링 연산자
UNION집합의 합집합 연산자
EXCEPT집합의 차집합 연산자
INTERSECT집합의 교집합 연산자
SORT정렬 연산자
TOP-N정렬 후 상위 N개 결과를 반환하는 연산자
TABLE FUNCTION NODE테이블 함수 연산자(lateral view)

공통 필드​

이름설명
limit출력 행 수를 제한합니다.
offset출력 전에 건너뛸 행 수입니다.
conjuncts현재 노드의 결과를 필터링합니다. projections 전에 실행됩니다.
projections현재 연산자 이후의 프로젝션 연산입니다. conjuncts 이후에 실행됩니다.
project output tuple id프로젝션 이후의 출력 튜플입니다. 데이터 튜플 내 슬롯 배치는 tuple desc에서 확인할 수 있습니다.
cardinality옵티마이저가 추정한 행 수입니다.
distribute expr lists현재 노드의 자식 노드에 대한 원래 데이터 분산 방식입니다.
표현식의 slot idslot id에 해당하는 슬롯은 verbose 모드의 튜플 목록에서 확인할 수 있습니다. 이 목록은 슬롯 유형과 null 허용 속성 등의 정보를 제공합니다. 표현식 뒤에 [#5]로 표시됩니다.

AGGREGATE​

이름설명
(집계 단계)집계 단계는 두 용어로 표시됩니다.
첫 번째 용어는 update(로컬 집계) 또는 merge(전역 집계)입니다.
두 번째 용어는 현재 데이터가 직렬화된 상태인지(serialize), 최종 계산을 완료한 상태인지(finalize) 나타냅니다.
STREAMING다단계 집계 절단 과정의 로컬 집계 연산자에만 이 플래그가 있습니다. 현재 집계 노드가 STREAMING 모드를 사용할 수 있음을 나타냅니다. 이 모드에서는 실제 계산 없이 입력 데이터를 다음 집계 단계로 직접 전달합니다.
output현재 집계 연산자의 출력입니다. 모든 로컬 사전 집계 함수에는 partial 접두사가 붙습니다.
group by집계에 사용하는 키입니다.

ANALYTIC​

이름설명
functions현재 윈도우 함수의 이름입니다.
partition by윈도우 함수의 over 절에 있는 partition by 절에 해당합니다. 윈도우 지정 표현식입니다.
order by윈도우 내 정렬 표현식과 정렬 순서입니다.
window윈도우 범위입니다.

ASSERT NUMBER OF ROWS​

이름설명
EQ다운스트림 출력은 이 행 수 제약 조건을 충족해야 합니다.

HASH JOIN​

이름설명
join op조인 유형입니다.
equal join conjunct조인 조건의 동등 조건입니다.
other join predicates조인 조건 중 동등 조건을 제외한 조건입니다.
mark join predicates마크 조인에 사용되는 조건입니다.
other predicates조인 실행 이후의 필터링 조건입니다.
runtime filters생성된 런타임 필터입니다.
output slot ids최종 출력 슬롯 목록입니다.
hash output slot ids해시 조인 실행 후 다른 조인 조건을 적용하기 전의 출력 슬롯 목록입니다.
isMarkJoin마크 조인인지 나타냅니다.

NESTED LOOP JOIN​

이름설명
join op조인 연산 유형입니다.
join conjuncts조인 조건입니다.
mark join predicates마크 조인에 사용되는 조건입니다.
predicates조인 이후의 필터 조건입니다.
runtime filters생성된 런타임 필터입니다.
output slot ids최종 출력 슬롯 목록입니다.
isMarkJoin마크 조인인지 나타냅니다.

PartitionTopN​

이름설명
functions그룹별 필터 최적화가 적용되는 윈도우 함수입니다.
has global limit행 수에 대한 전역 제한이 있는지 나타냅니다.
partition limit각 파티션 내 행 수 제한입니다.
partition topn phase현재 단계입니다. TWO_PHASE_GLOBAL_PTOPN은 파티션 키로 셔플한 이후의 전역 단계이고, TWO_PHASE_LOCAL_PTOPN은 파티션 키로 셔플하기 전의 로컬 단계입니다.

REPEAT_NODE​

이름설명
repeat각 행의 반복 횟수와 집계 컬럼에 해당하는 슬롯 ID입니다.
exprs반복 이후 출력 데이터의 표현식 목록입니다.

DataGenScanNode​

이름설명
table value function테이블 함수 이름입니다.

EsScanNode​

이름설명
SORT COLUMN결과 정렬에 사용하는 컬럼입니다.
LOCAL_PREDICATESDoris 내에서 실행되는 필터입니다.
REMOTE_PREDICATESES 내에서 실행되는 필터입니다.
ES index/type쿼리에 사용하는 ES 인덱스와 유형입니다.

HIVE_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.

HUDI_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
hudiNativeReadSplits네이티브 방식으로 읽는 분할 수입니다.

ICEBERG_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
icebergPredicatePushdowniceberg API로 푸시다운된 필터입니다.

PAIMON_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
paimonNativeReadSplits네이티브 방식으로 읽는 분할 수입니다.

NESTED LOOP JOIN​

이름설명
join op조인 연산 유형입니다.
join conjuncts조인 조건입니다.
mark join predicates마크 조인에 사용되는 조건입니다.
predicates조인 이후의 필터 조건입니다.
runtime filters생성된 런타임 필터입니다.
output slot ids최종 출력 슬롯 목록입니다.
isMarkJoin마크 조인인지 나타냅니다.

PartitionTopN​

이름설명
functions그룹별 필터 최적화가 적용되는 윈도우 함수입니다.
has global limit행 수에 대한 전역 제한이 있는지 나타냅니다.
partition limit각 파티션 내 행 수 제한입니다.
partition topn phase현재 단계입니다. TWO_PHASE_GLOBAL_PTOPN은 파티션 키로 셔플한 이후의 전역 단계이고, TWO_PHASE_LOCAL_PTOPN은 파티션 키로 셔플하기 전의 로컬 단계입니다.

REPEAT_NODE​

이름설명
repeat각 행의 반복 횟수와 집계 컬럼에 해당하는 슬롯 ID입니다.
exprs반복 이후 출력 데이터의 표현식 목록입니다.

DataGenScanNode​

이름설명
table value function테이블 함수 이름입니다.

EsScanNode​

이름설명
SORT COLUMN결과 정렬에 사용하는 컬럼입니다.
LOCAL_PREDICATESDoris 내에서 실행되는 필터입니다.
REMOTE_PREDICATESES 내에서 실행되는 필터입니다.
ES index/type쿼리에 사용하는 ES 인덱스와 유형입니다.

HIVE_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.

HUDI_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
hudiNativeReadSplits네이티브 방식으로 읽는 분할 수입니다.

ICEBERG_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
icebergPredicatePushdowniceberg API로 푸시다운된 필터입니다.

PAIMON_SCAN_NODE​

이름설명
inputSplitNum스캔 분할 수입니다.
totalFileSize스캔하는 파일의 전체 크기입니다.
scanRanges스캔 분할 정보입니다.
partition스캔하는 파티션 수입니다.
backends각 BE가 스캔할 데이터의 세부 정보입니다.
cardinality옵티마이저가 추정한 행 수입니다.
avgRowSize옵티마이저가 추정한 평균 행 크기입니다.
numNodes현재 연산자가 사용하는 BE 수입니다.
pushdown agg스캔으로 푸시다운된 집계입니다.
paimonNativeReadSplits네이티브 방식으로 읽는 분할 수입니다.

JdbcScanNode​

이름설명
TABLE스캔할 JDBC 측 테이블 이름입니다.
QUERY스캔에 사용하는 쿼리입니다.

OlapScanNode​

이름설명
TABLE스캔하는 테이블입니다. 괄호 안에는 쿼리에 활용된 동기식 구체화된 뷰의 이름이 표시됩니다.
SORT INFOSCAN 사전 정렬이 계획된 경우 표시됩니다. SCAN 출력의 부분 사전 정렬 및 사전 절단을 나타냅니다.
SORT LIMITSCAN 사전 정렬이 계획된 경우 표시됩니다. 사전 절단 시 유지할 길이를 나타냅니다.
TOPN OPTTOP-N Runtime Filter가 계획된 경우 표시됩니다.
PREAGGREGATION사전 집계가 활성화되어 있는지 나타냅니다. MOR 집계 모델 및 기본 키 모델과 관련이 있습니다. ON은 스토리지 계층의 데이터가 추가 집계 없이 상위 계층의 요구 사항을 충족함을 의미합니다. OFF는 추가 집계가 수행됨을 의미합니다.
partitions현재 스캔하는 파티션 수, 전체 파티션 수, 스캔하는 파티션 이름 목록입니다.
tablets스캔하는 태블릿 수와 테이블의 전체 태블릿 수입니다.
tabletList스캔하는 태블릿 목록입니다.
avgRowSize옵티마이저가 추정한 행 크기입니다.
numNodes현재 스캔에 할당된 BE 수입니다.
pushAggOpzonemap 메타데이터를 읽어 결과를 반환합니다. MIN, MAX, COUNT 집계 정보를 지원합니다.

UNION​

이름설명
constant exprs출력에 포함할 상수 표현식 목록입니다.
child exprs이 표현식 목록을 통해 자식 노드의 출력에 프로젝션을 적용하고, 그 결과를 집합 연산자의 입력으로 사용합니다.

EXCEPT​

이름설명
child exprs이 표현식 목록을 통해 자식 노드의 출력에 프로젝션을 적용하고, 그 결과를 집합 연산자의 입력으로 사용합니다.

INTERSECT​

이름설명
child exprs이 표현식 목록을 통해 자식 노드의 출력에 프로젝션을 적용하고, 그 결과를 집합 연산자의 입력으로 사용합니다.

SORT​

이름설명
order by정렬 키와 구체적인 정렬 순서입니다.

TABLE FUNCTION NODE​

이름설명
table function사용하는 테이블 함수의 이름입니다.
lateral view tuple id새로 생성된 컬럼에 해당하는 튜플 ID입니다.
output slot id컬럼 가지치기 이후 출력되는 컬럼의 슬롯 ID 목록입니다.

TOP-N​

이름설명
order by정렬 키와 구체적인 정렬 순서입니다.
TOPN OPTTOP-N 런타임 필터 최적화가 적용된 경우 표시됩니다.
OPT TWO PHASETOP-N 지연 구체화가 적용된 경우 표시됩니다.