인덱스의 본질 —
두꺼운 책의 찾아보기
섹션 5에서 원하는 데이터를 꺼내는 법을 익혔습니다. 이번 섹션은 같은 데이터를 어떻게 찾아가는가에 관한 이야기예요. 첫 강의는 비유 하나로 끝까지 갑니다 — 500쪽짜리 책과 맨 뒤의 찾아보기.
이번 섹션의 여정
완료 ✓
지금 여기
WHERE · JOIN · ORDER BY
단일 · 복합 · EXPLAIN · 비용
500쪽짜리 책에서 “향수”를 찾는 두 가지 방법
책상 위에 500쪽짜리 두꺼운 책이 있습니다. 여기서 “향수” 에 대한 설명을 찾아야 해요.
방법은 두 가지죠. 첫 페이지부터 한 장씩 넘겨도 언젠가는 찾습니다 — 시간이 꽤 걸릴 뿐이에요. 아니면 맨 뒤 찾아보기를 펼쳐 향수 … 312쪽을 확인하고, 곧장 312쪽으로 갑니다.
인덱스는 두꺼운 책의 찾아보기처럼, 찾을 값과 원본 데이터를 찾아갈 기본키를 미리 정리해 둔 구조입니다.
이 비유는 강의가 끝날 때까지 바뀌지 않습니다. 책의 본문은 테이블, 찾아보기는 인덱스, 페이지 번호는 기본키예요.
전체 스캔 — 결과 1행이 곧 “1행만 읽었다”는 뜻은 아닙니다
이번엔 진짜 shop DB에서 향수를 찾아보겠습니다.
SELECT product_id, product_name, price
FROM products
WHERE product_name = '향수';| product_id | product_name | price |
|---|---|---|
| 29 | 향수 | 89000 |
결과는 딱 한 줄입니다. 그런데 데이터베이스는 향수가 몇 번째 행에 있는지 미리 알고 있었을까요? 아니에요. product_name으로 찾아갈 길이 없으면 상품 행을 처음부터 끝까지 훑어보며 조건에 맞는 걸 골라냈을 수 있습니다.
결과 1행 ≠ 확인한 행 1개. 결과가 한 줄이라고 해서 한 줄만 들여다봤다는 뜻이 아닙니다. 눈에 보이는 건 골라낸 결과이지 읽은 양이 아니에요.
책을 첫 쪽부터 넘기는 것처럼 테이블 전체를 읽는 이 방법을 전체 스캔(Full Scan) 이라고 부릅니다.
30개일 때와 30만 개일 때
전체 스캔해도30행 확인은 눈 깜짝할 사이에 끝난다
체감인덱스가 있든 없든 차이를 느끼기 어렵다
전체 스캔이면한 번 검색에 30만 행을 다 읽는다
체감여기서부터 인덱스가 있고 없고가 갈린다
그래서 인덱스는 지금 느려서 배우는 게 아니라 — 데이터가 늘어날 때 무엇이 달라지는지 알기 위해 배웁니다.
shop 에는 이미 인덱스가 있습니다 — 다만 이름 컬럼엔 없습니다
init.sql에는 CREATE INDEX 문이 한 줄도 없습니다. 그런데 인덱스가 하나도 없는 건 아니에요. 기본키는 그 자체가 인덱스이고, 외래키를 만들면 InnoDB가 자식 컬럼에 인덱스를 자동으로 만들어 줍니다.
| 테이블 | 있는 인덱스 | 어디서 생겼나 |
|---|---|---|
| members | PRIMARY (member_id) | 기본키 |
| categories | PRIMARY (category_id) | 기본키 |
| products | PRIMARY (product_id) · category_id | 기본키 + 외래키 생성 시 자동 |
| orders | PRIMARY (order_id) · member_id | 기본키 + 외래키 생성 시 자동 |
| order_items | PRIMARY (order_id, product_id) · product_id | 복합 기본키 + 외래키 생성 시 자동 |
반대로 말하면 — members.member_name, members.age, products.product_name, products.price, orders.ordered_at 에는 아직 인덱스가 없습니다. 방금 우리가 향수를 찾은 product_name이 바로 그중 하나예요.
상품 이름에 찾아보기 하나 만들기
그럼 상품 테이블에도 찾아보기를 하나 붙여 보겠습니다.
CREATE INDEX idx_products_name
ON products (product_name);“상품 이름으로 더 쉽게 찾을 수 있도록, 상품 이름 컬럼에 인덱스를 만든다” — 딱 그 뜻입니다. idx_products_name은 그냥 이름표예요. 문자 그대로 읽지 말고 “상품 이름 인덱스” 라고 부르면 됩니다.
인덱스를 만들어도 products 30행이 통째로 복사되지 않습니다. 책 뒤 찾아보기가
본문을 베껴 적지 않는 것처럼 — 이름과 상품 번호만 따로 정리해 둘 뿐이에요.
찾아보기에 적히는 것 — 값과 기본키
책의 찾아보기에는 두 가지가 나란히 적혀 있었죠. 단어와 페이지 번호. 인덱스도 똑같이 두 가지를 담습니다.
products에서 상품 번호 product_id는 상품마다 하나씩 붙는 기본키입니다. 그래서 상품 이름 인덱스에는 향수라는 값과 기본키 값 29가 함께 정리돼요.
| 두꺼운 책 | products 테이블 | 무엇을 뜻하나 |
|---|---|---|
| 본문 500쪽 | 상품 30행 | 실제 데이터가 있는 원본 |
| 1쪽부터 한 장씩 넘기기 | 행을 처음부터 끝까지 확인 | 전체 스캔 |
| 맨 뒤 찾아보기 | product_name 인덱스 | 검색용으로 따로 만든 구조 |
| 찾아보기의 단어 "향수" | 인덱스에 저장된 값 "향수" | 찾을 값 |
| 페이지 번호 312쪽 | 기본키 product_id 29 | 원본으로 찾아가는 길 |
그리고 하나 더. 책의 찾아보기는 가나다순으로 정렬돼 있습니다. 그래서 첫 항목부터 훑지 않고 “ㅎ” 근처를 바로 펼칠 수 있어요.
인덱스도 마찬가지입니다. 값이 정렬된 상태로 유지되고, 상품이 추가되거나 이름이 바뀌어도 그 정렬은 계속 지켜집니다. 인덱스가 빠른 이유는 사본이 하나 더 있어서가 아니라 — 정렬돼 있어서 찾아볼 범위를 확 줄일 수 있기 때문입니다.
만들었다고 항상 쓰는 것은 아닙니다
여기서 많이들 놀랍니다. 찾아보기가 있다고 항상 펼쳐보는 건 아니거든요.
500쪽짜리 책이면 찾아보기가 훨씬 편하죠. 그런데 30쪽짜리 얇은 책이라면? 그냥 처음부터 넘기는 편이 빠릅니다. 우리 products도 30개뿐이라, 인덱스를 만든 뒤에도 데이터베이스가 전체 스캔을 고를 수 있어요.
이유는 하나 더 있습니다. 찾는 값이 너무 흔할 때도 그렇습니다.
| 조건 | 해당하는 행 | 값이 얼마나 흔한가 |
|---|---|---|
| product_name = '향수' | 30개 중 1개 | 드문 값 — 찾아보기가 제 몫을 하는 조건 |
| members.gender = 'F' | 20명 중 10명 | 절반 — 찾아보기를 펴도 결국 거의 다 읽는다 |
인덱스 생성 ≠ 인덱스 사용. 인덱스는 찾아갈 길을 하나 더 놓아줄 뿐이고, 실제로 어느 길로 갈지는 데이터베이스가 그때그때 판단합니다.
그러니 인덱스를 만든 뒤에 전체 스캔이 선택되더라도 실패가 아닙니다. 데이터가 적거나 값이 흔할 때 나올 수 있는 정상적인 판단이에요.
그럼 어느 길로 갔는지는 어떻게 확인할까요. 이때 쓰는 도구가 EXPLAIN입니다.
EXPLAIN(익스플레인)은 데이터베이스가 예상한 검색 방법을 보여주는
도구입니다. 실제 실행 시간을 재는 도구도, 인덱스 사용을 보장하는 명령도
아니에요. 결과표를 읽는 방법은 6-4 에서 천천히 다룹니다.
찾아보기도 공짜가 아닙니다
책의 모든 단어를 찾아보기에 넣으면 어떻게 될까요. 찾아보기 자체가 본문만큼 두꺼워지고, 본문이 한 줄 바뀔 때마다 찾아보기도 같이 고쳐야 합니다.
데이터베이스도 똑같습니다. 인덱스는 저장 공간을 쓰고, 상품이 추가되거나 상품 이름이 바뀌면 인덱스도 함께 정리해야 해요.
두 조건을 모두 만족하는 컬럼부터 인덱스 후보로 올려 두세요. 어떤 컬럼이 여기에 해당하는지는 다음 6-2 강의에서 하나씩 가려냅니다.
한눈에 정리
| 개념 | 책으로 말하면 | 데이터베이스에서는 |
|---|---|---|
| 원본 데이터 | 500쪽 본문 | products 테이블의 행 |
| 전체 스캔 | 1쪽부터 한 장씩 넘기기 | 행을 처음부터 끝까지 확인 |
| 인덱스 | 맨 뒤 찾아보기 | 찾을 값 + 기본키를 정렬해 둔 구조 |
| 인덱스로 찾기 | 향수 → 312쪽 → 본문 | 향수 → product_id 29 → 원본 상품 행 |
| 만들어도 안 쓸 수 있다 | 얇은 책은 그냥 넘긴다 | 데이터가 적거나 값이 흔하면 전체 스캔 |
| 확인 도구 | — | EXPLAIN — 예상 검색 방법 (6-4) |
순서로 기억하면 간단합니다. 전체를 읽고 있는지 살펴보고 → 필요한 인덱스를 만들고 → EXPLAIN으로 실제 선택을 확인한다.
이제 인덱스가 무엇인지는 알았습니다. 그런데 우리 shop의 수많은 컬럼 중 어디에 찾아보기를 붙여야 할까요? 다음 강의에서 그 후보를 고르는 기준을 잡습니다.