EXPLAIN
EXPLAIN
문장을 실행하지 않고 논리적·분산 실행 계획을 보여주거나 그 문장을 검증할 때 쓰는 명령어예요. 쿼리가 어떤 단계로 실행될지 미리 들여다보고 싶을 때 유용해요.
출처: 문서
본문
Synopsis
EXPLAIN [ ( option [, ...] ) ] statement
이때 option은 다음 중 하나일 수 있어요:
FORMAT { TEXT | GRAPHVIZ | JSON }
TYPE { LOGICAL | DISTRIBUTED | VALIDATE | IO }
Description
문장의 논리적 또는 분산 실행 계획을 보여주거나, 문장을 검증해요.
기본적으로 분산 계획이 표시돼요. 분산 계획의 각 계획 프래그먼트(fragment)는 단일 또는 여러 Trino 노드에서 실행돼요. 프래그먼트의 분리는 Trino 노드 간의 데이터 교환을 나타내요. 프래그먼트 타입은 프래그먼트가 Trino 노드에서 어떻게 실행되고 데이터가 프래그먼트 사이에 어떻게 분산되는지를 지정해요:
SINGLE- 프래그먼트가 단일 노드에서 실행돼요.HASH- 프래그먼트가 입력 데이터를 해시 함수로 분산해 고정된 수의 노드에서 실행돼요.ROUND_ROBIN- 프래그먼트가 입력 데이터를 라운드로빈 방식으로 분산해 고정된 수의 노드에서 실행돼요.BROADCAST- 프래그먼트가 입력 데이터를 모든 노드에 브로드캐스트해 고정된 수의 노드에서 실행돼요.SOURCE- 프래그먼트가 입력 스플릿(split)에 접근하는 노드에서 실행돼요.
EXPLAIN (TYPE LOGICAL)
Warning
EXPLAIN (TYPE LOGICAL)은 더 이상 사용되지 않으며(deprecated) 향후 릴리스에서 제거될 예정이에요. 대신 EXPLAIN (TYPE DISTRIBUTED)을 사용하세요.
제공된 쿼리 문장을 처리해 논리적 계획을 텍스트 형식으로 만들어요:
EXPLAIN (TYPE LOGICAL) SELECT regionkey, count(*) FROM nation GROUP BY 1;
Query Plan
-----------------------------------------------------------------------------------------------------------------
Trino version: version
Output[regionkey, _col1]
│ Layout: [regionkey:bigint, count:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ _col1 := count
└─ RemoteExchange[GATHER]
│ Layout: [regionkey:bigint, count:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
└─ Aggregate(FINAL)[regionkey]
│ Layout: [regionkey:bigint, count:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ count := count("count_8")
└─ LocalExchange[HASH][$hashvalue] ("regionkey")
│ Layout: [regionkey:bigint, count_8:bigint, $hashvalue:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
└─ RemoteExchange[REPARTITION][$hashvalue_9]
│ Layout: [regionkey:bigint, count_8:bigint, $hashvalue_9:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
└─ Project[]
│ Layout: [regionkey:bigint, count_8:bigint, $hashvalue_10:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ $hashvalue_10 := "combine_hash"(bigint '0', COALESCE("$operator$hash_code"("regionkey"), 0))
└─ Aggregate(PARTIAL)[regionkey]
│ Layout: [regionkey:bigint, count_8:bigint]
│ count_8 := count(*)
└─ TableScan[tpch:nation:sf0.01]
Layout: [regionkey:bigint]
Estimates: {rows: 25 (225B), cpu: 225, memory: 0B, network: 0B}
regionkey := tpch:regionkey
EXPLAIN (TYPE LOGICAL, FORMAT JSON)
Warning
출력 형식은 Trino 버전 간에 하위 호환성을 보장하지 않아요.
Warning
EXPLAIN (TYPE LOGICAL)은 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정이에요. 대신 EXPLAIN (TYPE DISTRIBUTED)을 사용하세요.
제공된 쿼리 문장을 처리해 논리적 계획을 JSON 형식으로 만들어요:
EXPLAIN (TYPE LOGICAL, FORMAT JSON) SELECT regionkey, count(*) FROM nation GROUP BY 1;
{
"id": "9",
"name": "Output",
"descriptor": {
"columnNames": "[regionkey, _col1]"
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count",
"type": "bigint"
}
],
"details": [
"_col1 := count"
],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "145",
"name": "RemoteExchange",
"descriptor": {
"type": "GATHER",
"isReplicateNullsAndAny": "",
"hashColumn": ""
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count",
"type": "bigint"
}
],
"details": [
],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "4",
"name": "Aggregate",
"descriptor": {
"type": "FINAL",
"keys": "[regionkey]",
"hash": ""
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count",
"type": "bigint"
}
],
"details": [
"count := count(\"count_0\")"
],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "194",
"name": "LocalExchange",
"descriptor": {
"partitioning": "HASH",
"isReplicateNullsAndAny": "",
"hashColumn": "[$hashvalue]",
"arguments": "[\"regionkey\"]"
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count_0",
"type": "bigint"
},
{
"symbol": "$hashvalue",
"type": "bigint"
}
],
"details":[],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "200",
"name": "RemoteExchange",
"descriptor": {
"type": "REPARTITION",
"isReplicateNullsAndAny": "",
"hashColumn": "[$hashvalue_1]"
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count_0",
"type": "bigint"
},
{
"symbol": "$hashvalue_1",
"type": "bigint"
}
],
"details":[],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "226",
"name": "Project",
"descriptor": {},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count_0",
"type": "bigint"
},
{
"symbol": "$hashvalue_2",
"type": "bigint"
}
],
"details": [
"$hashvalue_2 := combine_hash(bigint '0', COALESCE(\"$operator$hash_code\"(\"regionkey\"), 0))"
],
"estimates": [
{
"outputRowCount": "NaN",
"outputSizeInBytes": "NaN",
"cpuCost": "NaN",
"memoryCost": "NaN",
"networkCost": "NaN"
}
],
"children": [
{
"id": "198",
"name": "Aggregate",
"descriptor": {
"type": "PARTIAL",
"keys": "[regionkey]",
"hash": ""
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
},
{
"symbol": "count_0",
"type": "bigint"
}
],
"details": [
"count_0 := count(*)"
],
"estimates":[],
"children": [
{
"id": "0",
"name": "TableScan",
"descriptor": {
"table": "hive:tpch_sf1_orc_part:nation"
},
"outputs": [
{
"symbol": "regionkey",
"type": "bigint"
}
],
"details": [
"regionkey := regionkey:bigint:REGULAR"
],
"estimates": [
{
"outputRowCount": 25,
"outputSizeInBytes": 225,
"cpuCost": 225,
"memoryCost": 0,
"networkCost": 0
}
],
"children": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
EXPLAIN (TYPE DISTRIBUTED)
제공된 쿼리 문장을 처리해 분산 계획을 텍스트 형식으로 만들어요. 분산 계획은 논리적 계획을 스테이지로 나누므로 워커 사이의 데이터 교환을 명시적으로 보여줘요:
EXPLAIN (TYPE DISTRIBUTED) SELECT regionkey, count(*) FROM nation GROUP BY 1;
Query Plan
------------------------------------------------------------------------------------------------------
Trino version: version
Fragment 0 [SINGLE]
Output layout: [regionkey, count]
Output partitioning: SINGLE []
Output[regionkey, _col1]
│ Layout: [regionkey:bigint, count:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ _col1 := count
└─ RemoteSource[1]
Layout: [regionkey:bigint, count:bigint]
Fragment 1 [HASH]
Output layout: [regionkey, count]
Output partitioning: SINGLE []
Aggregate(FINAL)[regionkey]
│ Layout: [regionkey:bigint, count:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ count := count("count_8")
└─ LocalExchange[HASH][$hashvalue] ("regionkey")
│ Layout: [regionkey:bigint, count_8:bigint, $hashvalue:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
└─ RemoteSource[2]
Layout: [regionkey:bigint, count_8:bigint, $hashvalue_9:bigint]
Fragment 2 [SOURCE]
Output layout: [regionkey, count_8, $hashvalue_10]
Output partitioning: HASH [regionkey][$hashvalue_10]
Project[]
│ Layout: [regionkey:bigint, count_8:bigint, $hashvalue_10:bigint]
│ Estimates: {rows: ? (?), cpu: ?, memory: ?, network: ?}
│ $hashvalue_10 := "combine_hash"(bigint '0', COALESCE("$operator$hash_code"("regionkey"), 0))
└─ Aggregate(PARTIAL)[regionkey]
│ Layout: [regionkey:bigint, count_8:bigint]
│ count_8 := count(*)
└─ TableScan[tpch:nation:sf0.01, grouped = false]
Layout: [regionkey:bigint]
Estimates: {rows: 25 (225B), cpu: 225, memory: 0B, network: 0B}
regionkey := tpch:regionkey
EXPLAIN (TYPE DISTRIBUTED, FORMAT JSON)
Warning
출력 형식은 Trino 버전 간에 하위 호환성을 보장하지 않아요.
제공된 쿼리 문장을 처리해 분산 계획을 JSON 형식으로 만들어요. 분산 계획은 논리적 계획을 스테이지로 나누므로 워커 사이의 데이터 교환을 명시적으로 보여줘요:
EXPLAIN (TYPE DISTRIBUTED, FORMAT JSON) SELECT regionkey, count(*) FROM nation GROUP BY 1;
{
"0" : {
"id" : "9",
"name" : "Output",
"descriptor" : {
"columnNames" : "[regionkey, _col1]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count",
"type" : "bigint"
} ],
"details" : [ "_col1 := count" ],
"estimates" : [ {
"outputRowCount" : "NaN",
"outputSizeInBytes" : "NaN",
"cpuCost" : "NaN",
"memoryCost" : "NaN",
"networkCost" : "NaN"
} ],
"children" : [ {
"id" : "145",
"name" : "RemoteSource",
"descriptor" : {
"sourceFragmentIds" : "[1]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count",
"type" : "bigint"
} ],
"details" : [ ],
"estimates" : [ ],
"children" : [ ]
} ]
},
"1" : {
"id" : "4",
"name" : "Aggregate",
"descriptor" : {
"type" : "FINAL",
"keys" : "[regionkey]",
"hash" : "[]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count",
"type" : "bigint"
} ],
"details" : [ "count := count(\"count_0\")" ],
"estimates" : [ {
"outputRowCount" : "NaN",
"outputSizeInBytes" : "NaN",
"cpuCost" : "NaN",
"memoryCost" : "NaN",
"networkCost" : "NaN"
} ],
"children" : [ {
"id" : "194",
"name" : "LocalExchange",
"descriptor" : {
"partitioning" : "SINGLE",
"isReplicateNullsAndAny" : "",
"hashColumn" : "[]",
"arguments" : "[]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count_0",
"type" : "bigint"
} ],
"details" : [ ],
"estimates" : [ {
"outputRowCount" : "NaN",
"outputSizeInBytes" : "NaN",
"cpuCost" : "NaN",
"memoryCost" : "NaN",
"networkCost" : "NaN"
} ],
"children" : [ {
"id" : "227",
"name" : "Project",
"descriptor" : { },
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count_0",
"type" : "bigint"
} ],
"details" : [ ],
"estimates" : [ {
"outputRowCount" : "NaN",
"outputSizeInBytes" : "NaN",
"cpuCost" : "NaN",
"memoryCost" : "NaN",
"networkCost" : "NaN"
} ],
"children" : [ {
"id" : "200",
"name" : "RemoteSource",
"descriptor" : {
"sourceFragmentIds" : "[2]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count_0",
"type" : "bigint"
}, {
"symbol" : "$hashvalue",
"type" : "bigint"
} ],
"details" : [ ],
"estimates" : [ ],
"children" : [ ]
} ]
} ]
} ]
},
"2" : {
"id" : "226",
"name" : "Project",
"descriptor" : { },
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count_0",
"type" : "bigint"
}, {
"symbol" : "$hashvalue_1",
"type" : "bigint"
} ],
"details" : [ "$hashvalue_1 := combine_hash(bigint '0', COALESCE(\"$operator$hash_code\"(\"regionkey\"), 0))" ],
"estimates" : [ {
"outputRowCount" : "NaN",
"outputSizeInBytes" : "NaN",
"cpuCost" : "NaN",
"memoryCost" : "NaN",
"networkCost" : "NaN"
} ],
"children" : [ {
"id" : "198",
"name" : "Aggregate",
"descriptor" : {
"type" : "PARTIAL",
"keys" : "[regionkey]",
"hash" : "[]"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
}, {
"symbol" : "count_0",
"type" : "bigint"
} ],
"details" : [ "count_0 := count(*)" ],
"estimates" : [ ],
"children" : [ {
"id" : "0",
"name" : "TableScan",
"descriptor" : {
"table" : "tpch:tiny:nation"
},
"outputs" : [ {
"symbol" : "regionkey",
"type" : "bigint"
} ],
"details" : [ "regionkey := tpch:regionkey" ],
"estimates" : [ {
"outputRowCount" : 25.0,
"outputSizeInBytes" : 225.0,
"cpuCost" : 225.0,
"memoryCost" : 0.0,
"networkCost" : 0.0
} ],
"children" : [ ]
} ]
} ]
}
}
EXPLAIN (TYPE VALIDATE)
제공된 쿼리 문장을 구문적으로·의미적으로 올바른지 검증해요. 문장이 유효하면 true를 반환해요:
EXPLAIN (TYPE VALIDATE) SELECT regionkey, count(*) FROM nation GROUP BY 1;
Valid
-------
true
알 수 없는 키워드 같은 구문 오류로 문장이 올바르지 않으면 오류 메시지가 문제를 자세히 설명해요:
EXPLAIN (TYPE VALIDATE) SELET 1=0;
Query 20220929_234840_00001_vjwxj failed: line 1:25: mismatched input 'SELET'.
Expecting: 'ALTER', 'ANALYZE', 'CALL', 'COMMENT', 'COMMIT', 'CREATE',
'DEALLOCATE', 'DELETE', 'DENY', 'DESC', 'DESCRIBE', 'DROP', 'EXECUTE',
'EXPLAIN', 'GRANT', 'INSERT', 'MERGE', 'PREPARE', 'REFRESH', 'RESET',
'REVOKE', 'ROLLBACK', 'SET', 'SHOW', 'START', 'TRUNCATE', 'UPDATE', 'USE',
마찬가지로, 유효하지 않은 객체 이름(예: nation 대신 nations) 같은 의미적 문제가 감지되면 오류 메시지가 유용한 정보를 반환해요:
EXPLAIN(TYPE VALIDATE) SELECT * FROM tpch.tiny.nations;
Query 20220929_235059_00003_vjwxj failed: line 1:15: Table 'tpch.tiny.nations' does not exist
SELECT * FROM tpch.tiny.nations
EXPLAIN (TYPE IO)
제공된 쿼리 문장을 처리해 접근한 객체의 입력·출력 정보를 JSON 형식으로 담은 계획을 만들어요:
EXPLAIN (TYPE IO, FORMAT JSON) INSERT INTO test_lineitem
SELECT * FROM lineitem WHERE shipdate = '2020-02-01' AND quantity > 10;
Query Plan
-----------------------------------
{
inputTableColumnInfos: [
{
table: {
catalog: "hive",
schemaTable: {
schema: "tpch",
table: "test_orders"
}
},
columnConstraints: [
{
columnName: "orderkey",
type: "bigint",
domain: {
nullsAllowed: false,
ranges: [
{
low: {
value: "1",
bound: "EXACTLY"
},
high: {
value: "1",
bound: "EXACTLY"
}
},
{
low: {
value: "2",
bound: "EXACTLY"
},
high: {
value: "2",
bound: "EXACTLY"
}
}
]
}
},
{
columnName: "processing",
type: "boolean",
domain: {
nullsAllowed: false,
ranges: [
{
low: {
value: "false",
bound: "EXACTLY"
},
high: {
value: "false",
bound: "EXACTLY"
}
}
]
}
},
{
columnName: "custkey",
type: "bigint",
domain: {
nullsAllowed: false,
ranges: [
{
low: {
bound: "ABOVE"
},
high: {
value: "10",
bound: "EXACTLY"
}
}
]
}
}
],
estimate: {
outputRowCount: 2,
outputSizeInBytes: 40,
cpuCost: 40,
maxMemory: 0,
networkCost: 0
}
}
],
outputTable: {
catalog: "hive",
schemaTable: {
schema: "tpch",
table: "test_orders"
}
},
estimate: {
outputRowCount: "NaN",
outputSizeInBytes: "NaN",
cpuCost: "NaN",
maxMemory: "NaN",
networkCost: "NaN"
}
}
See also
EXPLAIN ANALYZE 명령과 함께 사용해요.
더 알아보기 (Learn more)
실제 실행과 함께 각 연산의 비용을 확인하려면 EXPLAIN ANALYZE도 함께 살펴보세요.