바이브 코딩 시대의 데이터베이스6-4 EXPLAIN — 실행 계획 읽기
테크타니 LEARN — 섹션 06 · 인덱스

EXPLAIN —
SQL이 데이터를 찾는 길 미리 보기

내비게이션에 목적지를 입력하면 출발하기 전에 예상 경로가 먼저 나오죠. 어느 길로 갈지, 얼마나 걸릴지를 미리 보여줍니다. 데이터베이스에도 같은 기능이 있어요 — EXPLAIN입니다.

난이도보통소요8분준비물6-3 완료오늘type · key · rows 세 칸만

이번 섹션의 여정

6-1 인덱스의 본질

완료 ✓

→
6-2 언제 만들까

완료 ✓

→
6-3 단일 · 복합 인덱스

완료 ✓

→
6-4 EXPLAIN

지금 여기

실행하기 전에 계획을 먼저 봅니다

지금까지 인덱스를 만들었습니다. 그런데 — 데이터베이스가 그 인덱스를 정말 쓰고 있을까요?

6-1에서 봤듯 인덱스가 있어도 안 쓸 수 있고, 6-3에서 봤듯 컬럼 순서가 맞지 않으면 못 쓰기도 합니다. 짐작만 해서는 알 수 없어요. EXPLAIN이 그걸 보여줍니다.

EXPLAIN 이 하는 일

EXPLAIN 은 SQL 을 실행하기 전에, 데이터베이스가 데이터를 어떻게 찾을지 보여주는 예상 경로입니다.

결과를 보여주는 기능이 아닙니다

EXPLAIN 은 실제 데이터를 꺼내오지 않습니다. 데이터를 찾을 계획만 보여줘요. 실제 결과가 궁금하면 EXPLAIN 을 떼고 그냥 실행하면 됩니다.

쓰는 법 — SELECT 앞에 붙이기

사용법은 아주 간단합니다. 확인하고 싶은 SELECT 문 앞에 EXPLAIN을 붙이면 끝이에요.

DBeaver — SQL 편집기
EXPLAIN
SELECT product_id, product_name, price
FROM products
WHERE product_id = 29;

상품 번호 29번(향수)을 데이터베이스가 어떻게 찾을지 확인하는 겁니다. 실행하면 칸이 열 개도 넘게 나오는데 — 처음부터 전부 볼 필요는 없어요.

EXPLAIN 결과 — 오늘 볼 세 칸만
typekeyrows
constPRIMARY1
type = 어떻게 찾는가 · key = 어떤 인덱스를 골랐나 · rows = 몇 행을 볼 예정인가
실제로는 id · select_type · possible_keys · key_len · ref · filtered · Extra 도 함께 나옵니다

type — 어떻게 찾는가

type은 데이터를 어떤 방식으로 찾는지를 보여줍니다.

지금은 기본키인 상품 번호로 딱 한 상품을 찾고 있죠. 이런 경우 보통 const가 표시됩니다.

자주 보게 되는 type 값
type뜻언제 나오나
const하나의 값으로 대상을 아주 좁게 찾는다기본키 · 유니크 키로 한 행을 콕 집을 때
ref인덱스로 조건에 맞는 몇 행을 찾는다외래키 인덱스 등으로 여러 행을 고를 때
range인덱스에서 범위 구간을 훑는다부등호 · BETWEEN · IN 조건
ALL테이블을 처음부터 끝까지 살펴본다쓸 인덱스가 없을 때
위로 갈수록 좁게 찾고, 아래로 갈수록 넓게 봅니다
ALL 이 나왔다고 무조건 잘못은 아닙니다

데이터가 몇 개 없는 작은 테이블이라면 전체를 보는 편이 오히려 빠를 수 있어요. 우리 products 는 30행뿐이라 그렇습니다. ALL 은 “넓게 보고 있다” 는 신호이지, 그 자체로 오류는 아닙니다.

key — 어떤 인덱스를 골랐는가

key는 데이터를 찾을 때 실제로 선택한 인덱스의 이름을 보여줍니다.

이번 조회에서는 상품 번호가 기본키이므로 PRIMARY가 보입니다.

key 를 읽는 법
key 값뜻
PRIMARY기본키 인덱스를 선택했다
idx_products_name6-1 에서 직접 만든 인덱스를 선택했다
fk_orders_member외래키를 만들 때 자동 생성된 인덱스를 선택했다
NULL이번 조회에서 선택한 인덱스가 없다
key 가 NULL 인데 테이블이 크다면 — 인덱스를 검토할 자리입니다
possible_keys 와는 다릅니다

possible_keys 는 “쓸 수 있었던 후보”, key 는 “실제로 고른 것” 입니다. 후보에 이름이 있는데 key 가 NULL 이라면 — 옵티마이저가 쓸 수 있었지만 안 쓰기로 판단한 겁니다.

rows — 몇 행을 살펴볼 예정인가

마지막은 rows입니다. 데이터베이스가 살펴볼 것으로 예상한 행의 수예요.

여기서 아주 중요한 지점이 있습니다.

rows 는 무엇이 아닌가
이런 숫자일까?답
실제 검색 결과의 개수✕ 아닙니다
실제로 읽은 행을 센 숫자✕ 아닙니다
데이터베이스가 미리 계산한 예상값○ 맞습니다
예상값이라서 — 실행 환경이나 통계 상태에 따라 조금씩 달라질 수 있습니다

그래서 rows는 정확한 측정값이 아니라 규모의 감각으로 읽어야 합니다. 1과 30은 큰 차이가 없지만, 1과 2,000,000은 완전히 다른 이야기죠.

세 칸을 한 문장으로 읽기

이제 세 칸을 한 번에 읽어보겠습니다.

EXPLAIN 결과 (products WHERE product_id = 29)
typekeyrows
constPRIMARY1
const 방식으로 · 기본키 인덱스를 사용해 · 한 행 정도를 살펴볼 계획입니다

이렇게 한 문장으로 이어 읽으면 됩니다. 영어 단어와 숫자를 따로 외우는 것보다 훨씬 쉬워요.

비교를 위해 인덱스를 못 쓰는 조회도 볼게요. price에는 인덱스가 없습니다.

DBeaver — SQL 편집기
EXPLAIN
SELECT product_id, product_name, price
FROM products
WHERE price >= 50000;
같은 테이블, 다른 조건
조회 조건typekeyrows한 문장으로 읽으면
product_id = 29constPRIMARY1기본키로 한 행을 콕 집는다
price >= 50000ALLNULL30쓸 인덱스가 없어 30행을 전부 훑는다
같은 테이블인데 조건에 따라 경로가 완전히 달라집니다
rows 는 예상값이라 실행 환경에 따라 30 근처의 다른 값이 나올 수 있습니다
⭐ 꼭 구분하세요EXPLAIN 은 예상 경로, SELECT 는 실제 결과입니다.

한눈에 정리

칸무엇을 알려주나이렇게 읽습니다
type데이터를 찾는 방법const 좁게 · ALL 전체 훑기
key실제로 선택한 인덱스이름이 보이면 사용 · NULL 이면 미사용
rows살펴볼 것으로 예상한 행 수측정값이 아니라 예상값 — 규모로 읽는다

EXPLAIN은 인덱스를 만든 뒤 정말 쓰이고 있는지 확인하는 도구입니다. 짐작 대신 확인하세요 — 세 칸을 한 문장으로 이어 읽으면 충분합니다.

그런데 인덱스가 좋다면 많이 만들수록 좋을까요? 다음 강의에서 인덱스의 비용과 함정을 봅니다.

NEXT LESSON6-5 인덱스의 비용과 함정 — 많다고 모두 빨라지지 않는다

저장 공간과 쓰기 비용, 그리고 인덱스를 만들어 두고도 못 쓰게 되는 두 가지 함정을 봅니다.

GO ▸ 6-5 시작하기