복합 인덱스 (Composite Index)
핵심 개념
여러 컬럼을 하나의 인덱스로 묶은 것.
CREATE INDEX idx_user_date
ON orders (user_id, created_at);
인덱스 구조 (B-tree):
[user=5, 03-01]
/ \
[user=3, 02-15] [user=7, 03-10]
/ \
[user=1, [user=3,
01-20] 03-05]
최좌선 원칙 (Leftmost Prefix)
복합 인덱스 (A, B, C) 활용 여부:
| 쿼리 조건 | 인덱스 사용 |
|---|
WHERE A = ? | O (A만 사용) |
WHERE A = ? AND B = ? | O (A, B 사용) |
WHERE A = ? AND B = ? AND C = ? | O (전체 사용) |
WHERE B = ? | X (A 없음) |
WHERE B = ? AND C = ? | X (A 없음) |
WHERE A = ? AND C = ? | 일부 사용 (A 만) |
왼쪽부터 연속으로 사용해야 인덱스가 동작한다!
컬럼 순서 설계
규칙: 카디널리티 높은 컬럼 → 앞에
예시: 주문 테이블 검색
- status: 3종류 (카디널리티 낮음)
- user_id: 10만 종류 (카디널리티 높음)
권장: INDEX (user_id, status)
→ user_id로 대부분 걸러짐
비권장: INDEX (status, user_id)
→ status로는 33%만 걸러짐
실무 예시: 쇼핑몰 주문 조회
-- 자주 쓰는 쿼리
SELECT * FROM orders
WHERE user_id = 123
AND status = 'completed'
ORDER BY created_at DESC;
-- 최적 인덱스
CREATE INDEX idx_orders_lookup
ON orders (user_id, status, created_at);
주의사항
- 인덱스는 쓰기 성능을 희생하는 대가
- 불필요한 복합 인덱스는 오히려 독
- 3-4개 컬럼이 적당 (그 이상은 재고)
Q.복합 인덱스의 최좌선 원칙(Leftmost Prefix Rule)을 설명해주세요
복합 인덱스는 앞 컬럼부터 차례로 정렬돼 있어서, 앞 컬럼을 건너뛰면 쓸 수 없습니다.
INDEX (A, B, C) 는 A 로 정렬하고, A 가 같으면 B, 또 같으면 C 로 정렬한다
| 조건 | 인덱스 사용 |
|---|
| A = ? | 사용 |
| A = ? AND B = ? | 사용 |
| A = ? AND B = ? AND C = ? | 사용 |
| B = ? | 사용 못 함 |
| B = ? AND C = ? | 사용 못 함 |
| A = ? AND C = ? | A 까지만 사용 |
전화번호부가 성으로 먼저 정렬돼 있으면 이름만으로는 찾을 수 없는 것과 같습니다.
범위 조건도 영향을 줍니다. A = ? AND B > ? AND C = ? 이면 B 까지 쓰고 C 는 정렬이 보장되지 않아 못 씁니다.
흔한 실수: 조건에 쓰인 컬럼이 모두 인덱스에 있으면 탄다고 보는 것. 순서가 규칙을 정합니다.
Q.복합 인덱스에서 컬럼 순서를 어떻게 결정하나요?
| 기준 | 내용 |
|---|
| 등가 조건을 앞에 | 범위 조건은 그 뒤부터 인덱스를 못 쓰게 만든다 |
| 선택도가 높은 것을 앞에 | 걸러내는 힘이 큰 컬럼이 앞에 오면 탐색 범위가 줄어든다 |
| 자주 쓰는 조합을 앞에 | 하나의 인덱스로 여러 쿼리를 덮을 수 있다 |
| ORDER BY 컬럼을 뒤에 | 정렬까지 인덱스로 해결하면 추가 정렬이 사라진다 |
첫 번째가 가장 강한 규칙입니다.
WHERE status = 'paid' AND created_at > ?
INDEX (status, created_at) -- 좋다
INDEX (created_at, status) -- 범위 뒤라 status 를 못 쓴다
선택도는 실제 데이터로 확인합니다. status 값이 두 개뿐이면 앞에 두어도 절반밖에 못 거릅니다.
흔한 실수: 무조건 카디널리티가 높은 컬럼을 앞에 두는 것. 등가와 범위의 구분이 우선이고, 그 다음이 선택도입니다.
Q.WHERE A = ? AND C = ? 쿼리가 INDEX(A, B, C)를 활용할 수 있나요?
A 까지만 활용합니다. B 가 빠져 C 의 정렬이 보장되지 않기 때문입니다.
INDEX (A, B, C) 의 정렬 순서
A=1, B=1, C=5
A=1, B=2, C=3 <- A 가 같아도 C 는 뒤죽박죽이다
A=1, B=2, C=9
A 로 범위를 좁힌 뒤 그 안에서 C 조건은 하나씩 확인해야 합니다. 인덱스를 타긴 하지만 C 는 걸러내는 데만 쓰이고 탐색 범위를 줄이지는 못합니다.
실행 계획에서 확인할 수 있습니다. 인덱스에서 실제로 사용한 길이를 보면 A 의 크기만 잡힙니다.
개선하려면 INDEX (A, C) 를 따로 만들거나, 그 쿼리가 중요하면 컬럼 순서를 바꿉니다.
흔한 실수: 아예 못 탄다고 답하는 것. A 로는 탑니다. 어디까지 쓰는지를 구분해 답하는 것이 요지입니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.