EXPLAIN
SQL 문장을 실제로 실행하지 않고도 어떻게 처리될지 들여다보게 해 주는 EXPLAIN 문이에요. 가상 머신 바이트코드를 보는 EXPLAIN과 쿼리 실행 전략을 보여 주는 EXPLAIN QUERY PLAN, 두 가지 형태가 있어요.
출처: 문서
본문
EXPLAIN 문은 Turso가 SQL 문장을 어떻게 실행하는지에 대한 정보를 보여 줘요. 두 가지 형태가 있는데, EXPLAIN은 가상 머신 바이트코드를 보여 주고 EXPLAIN QUERY PLAN은 더 높은 수준의 쿼리 실행 전략을 보여 줘요.
Syntax
EXPLAIN statement;
EXPLAIN QUERY PLAN statement;
| Parameter | Type | Description |
|---|---|---|
| statement | SQL | 어떤 SQL 문장이든 (SELECT, INSERT, UPDATE, DELETE 등) |
EXPLAIN
EXPLAIN 접두어를 붙이면 Turso가 문장을 실행하는 대신, 그 문장을 실행하는 데 쓰일 가상 머신(VDBE) opcode의 나열을 돌려줘요.
EXPLAIN SELECT * FROM users WHERE id = 1;
-- addr | opcode | p1 | p2 | p3 | p4 | p5
-- 0 | Init | 0 | 9 | 0 | | 0
-- 1 | OpenRead | 0 | 2 | 0 | 3 | 0
-- 2 | SeekRowid | 0 | 8 | 1 | | 0
-- ...
Output Columns
| Column | Description |
|---|---|
| addr | 명령어 주소 (순차적인 정수) |
| opcode | 연산 이름 (예: OpenRead, SeekRowid, Column, ResultRow) |
| p1 | 첫 번째 피연산자 |
| p2 | 두 번째 피연산자 |
| p3 | 세 번째 피연산자 |
| p4 | 네 번째 피연산자 (테이블 이름이나 콜레이션처럼 문자열 값인 경우가 많아요) |
| p5 | 다섯 번째 피연산자 (플래그) |
EXPLAIN QUERY PLAN
EXPLAIN QUERY PLAN 접두어는 쿼리 옵티마이저가 문장을 실행하기 위해 선택한 전략을 높은 수준에서 설명해 줘요. 쿼리 성능을 이해할 때는 날것의 EXPLAIN보다 이 출력이 훨씬 유용해요.
EXPLAIN QUERY PLAN SELECT * FROM users WHERE name = 'Alice';
-- id | parent | notused | detail
-- 2 | 0 | 0 | SCAN users
CREATE INDEX idx_name ON users(name);
EXPLAIN QUERY PLAN SELECT * FROM users WHERE name = 'Alice';
-- id | parent | notused | detail
-- 3 | 0 | 0 | SEARCH users USING INDEX idx_name (name=?)
Output Columns
| Column | Description |
|---|---|
| id | 이 단계의 고유 식별자 |
| parent | 부모 단계의 id (최상위는 0) |
| notused | 향후 사용을 위해 예약됨 (항상 0) |
| detail | 실행 단계를 사람이 읽을 수 있는 형태로 설명한 내용 |
Common Detail Messages
| Detail Pattern | Meaning |
|---|---|
SCAN table |
전체 테이블 스캔 (인덱스를 사용하지 않음) |
SEARCH table USING INDEX idx (col=?) |
지정한 컬럼에 대한 인덱스 조회 |
SEARCH table USING INTEGER PRIMARY KEY (rowid=?) |
rowid 직접 조회 |
USE TEMP B-TREE FOR ORDER BY |
정렬을 위해 임시 B-트리를 사용함 |
USE TEMP B-TREE FOR DISTINCT |
중복 제거를 위해 임시 B-트리를 사용함 |
COMPOUND SUBQUERY |
UNION, INTERSECT, EXCEPT 중 하나를 의미함 |
CORRELATED SCALAR SUBQUERY |
단일 값을 돌려주는 상관 서브쿼리 |
Examples
Comparing Query Plans
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER,
total REAL
);
-- 인덱스가 없을 때: 전체 테이블 스캔
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE customer_id = 42;
-- SCAN orders
-- 인덱스를 만든 후
CREATE INDEX idx_customer ON orders(customer_id);
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE customer_id = 42;
-- SEARCH orders USING INDEX idx_customer (customer_id=?)
Join Order
EXPLAIN QUERY PLAN
SELECT o.id, c.name
FROM orders o
INNER JOIN customers c ON c.id = o.customer_id
WHERE c.name = 'Alice';
-- SCAN orders AS o
-- SEARCH customers AS c USING INTEGER PRIMARY KEY (rowid=?)
Subqueries
EXPLAIN QUERY PLAN
SELECT * FROM orders
WHERE customer_id IN (SELECT id FROM customers WHERE active = 1);
-- SCAN orders
-- LIST SUBQUERY
-- SCAN customers
See Also
- ANALYZE for collecting statistics that improve query plans
- CREATE INDEX for creating indexes to speed up queries
더 알아보기 (Learn more)
- ANALYZE - 쿼리 플랜을 개선하는 통계 수집
- CREATE INDEX - 쿼리를 빠르게 하는 인덱스 생성
- SELECT - EXPLAIN으로 분석하게 되는 SELECT 문