EXPLAIN —
SQL이 데이터를 찾는 길 미리 보기
내비게이션에 목적지를 입력하면 출발하기 전에 예상 경로가 먼저 나오죠. 어느 길로 갈지, 얼마나 걸릴지를 미리 보여줍니다. 데이터베이스에도 같은 기능이 있어요 — EXPLAIN입니다.
이번 섹션의 여정
완료 ✓
완료 ✓
완료 ✓
지금 여기
실행하기 전에 계획을 먼저 봅니다
지금까지 인덱스를 만들었습니다. 그런데 — 데이터베이스가 그 인덱스를 정말 쓰고 있을까요?
6-1에서 봤듯 인덱스가 있어도 안 쓸 수 있고, 6-3에서 봤듯 컬럼 순서가 맞지 않으면 못 쓰기도 합니다. 짐작만 해서는 알 수 없어요. EXPLAIN이 그걸 보여줍니다.
EXPLAIN 은 SQL 을 실행하기 전에, 데이터베이스가 데이터를 어떻게 찾을지 보여주는 예상 경로입니다.
EXPLAIN 은 실제 데이터를 꺼내오지 않습니다. 데이터를 찾을 계획만
보여줘요. 실제 결과가 궁금하면 EXPLAIN 을 떼고 그냥 실행하면 됩니다.
쓰는 법 — SELECT 앞에 붙이기
사용법은 아주 간단합니다. 확인하고 싶은 SELECT 문 앞에 EXPLAIN을 붙이면 끝이에요.
상품 번호 29번(향수)을 데이터베이스가 어떻게 찾을지 확인하는 겁니다. 실행하면 칸이 열 개도 넘게 나오는데 — 처음부터 전부 볼 필요는 없어요.
| type | key | rows |
|---|---|---|
| const | PRIMARY | 1 |
type — 어떻게 찾는가
type은 데이터를 어떤 방식으로 찾는지를 보여줍니다.
지금은 기본키인 상품 번호로 딱 한 상품을 찾고 있죠. 이런 경우 보통 const가 표시됩니다.
| type | 뜻 | 언제 나오나 |
|---|---|---|
| const | 하나의 값으로 대상을 아주 좁게 찾는다 | 기본키 · 유니크 키로 한 행을 콕 집을 때 |
| ref | 인덱스로 조건에 맞는 몇 행을 찾는다 | 외래키 인덱스 등으로 여러 행을 고를 때 |
| range | 인덱스에서 범위 구간을 훑는다 | 부등호 · BETWEEN · IN 조건 |
| ALL | 테이블을 처음부터 끝까지 살펴본다 | 쓸 인덱스가 없을 때 |
데이터가 몇 개 없는 작은 테이블이라면 전체를 보는 편이 오히려 빠를 수
있어요. 우리 products 는 30행뿐이라 그렇습니다. ALL 은 “넓게 보고 있다”
는 신호이지, 그 자체로 오류는 아닙니다.
key — 어떤 인덱스를 골랐는가
key는 데이터를 찾을 때 실제로 선택한 인덱스의 이름을 보여줍니다.
이번 조회에서는 상품 번호가 기본키이므로 PRIMARY가 보입니다.
| key 값 | 뜻 |
|---|---|
| PRIMARY | 기본키 인덱스를 선택했다 |
| idx_products_name | 6-1 에서 직접 만든 인덱스를 선택했다 |
| fk_orders_member | 외래키를 만들 때 자동 생성된 인덱스를 선택했다 |
| NULL | 이번 조회에서 선택한 인덱스가 없다 |
possible_keys 는 “쓸 수 있었던 후보”, key 는 “실제로 고른 것” 입니다.
후보에 이름이 있는데 key 가 NULL 이라면 — 옵티마이저가 쓸 수 있었지만 안
쓰기로 판단한 겁니다.
rows — 몇 행을 살펴볼 예정인가
마지막은 rows입니다. 데이터베이스가 살펴볼 것으로 예상한 행의 수예요.
여기서 아주 중요한 지점이 있습니다.
| 이런 숫자일까? | 답 |
|---|---|
| 실제 검색 결과의 개수 | ✕ 아닙니다 |
| 실제로 읽은 행을 센 숫자 | ✕ 아닙니다 |
| 데이터베이스가 미리 계산한 예상값 | ○ 맞습니다 |
그래서 rows는 정확한 측정값이 아니라 규모의 감각으로 읽어야 합니다. 1과 30은 큰 차이가 없지만, 1과 2,000,000은 완전히 다른 이야기죠.
세 칸을 한 문장으로 읽기
이제 세 칸을 한 번에 읽어보겠습니다.
| type | key | rows |
|---|---|---|
| const | PRIMARY | 1 |
이렇게 한 문장으로 이어 읽으면 됩니다. 영어 단어와 숫자를 따로 외우는 것보다 훨씬 쉬워요.
비교를 위해 인덱스를 못 쓰는 조회도 볼게요. price에는 인덱스가 없습니다.
| 조회 조건 | type | key | rows | 한 문장으로 읽으면 |
|---|---|---|---|---|
| product_id = 29 | const | PRIMARY | 1 | 기본키로 한 행을 콕 집는다 |
| price >= 50000 | ALL | NULL | 30 | 쓸 인덱스가 없어 30행을 전부 훑는다 |
한눈에 정리
| 칸 | 무엇을 알려주나 | 이렇게 읽습니다 |
|---|---|---|
| type | 데이터를 찾는 방법 | const 좁게 · ALL 전체 훑기 |
| key | 실제로 선택한 인덱스 | 이름이 보이면 사용 · NULL 이면 미사용 |
| rows | 살펴볼 것으로 예상한 행 수 | 측정값이 아니라 예상값 — 규모로 읽는다 |
EXPLAIN은 인덱스를 만든 뒤 정말 쓰이고 있는지 확인하는 도구입니다. 짐작 대신 확인하세요 — 세 칸을 한 문장으로 이어 읽으면 충분합니다.
그런데 인덱스가 좋다면 많이 만들수록 좋을까요? 다음 강의에서 인덱스의 비용과 함정을 봅니다.