← 아티클 목록

복합 인덱스 설계 원칙 — 선두 컬럼과 카디널리티

2026-12-07#database#인덱스#성능

복합 인덱스를 만들 때 컬럼을 아무 순서로나 넣으면 인덱스가 있어도 안 타는 일이 생깁니다. (a, b, c)(c, b, a)는 완전히 다른 인덱스입니다. 순서를 정하는 원칙을 알면 인덱스를 추가하기 전에 효과를 예측할 수 있습니다.

선두 컬럼 규칙

복합 인덱스는 왼쪽 컬럼부터 차례대로만 사용할 수 있습니다. (user_id, status, created_at) 인덱스로 탈 수 있는 조건:

WHERE 조건인덱스 사용
user_id=42O (선두만 써도 됨)
user_id=42 AND status='paid'O (앞 2개)
status='paid'X (선두 건너뜀)
status='paid' AND created_at>...X (선두 없음)

status만으로 조회하면 인덱스를 못 탑니다. 선두 컬럼인 user_id가 조건에 없으면 그 뒤는 무의미합니다.

등호 먼저, 범위는 마지막

컬럼 순서의 핵심 규칙입니다. 등호(=) 조건 컬럼을 앞에, 범위(>, <, BETWEEN) 컬럼을 뒤에 둡니다. 범위 조건이 걸린 컬럼 이후의 컬럼은 인덱스 정렬을 더 못 씁니다.

SQL
-- 조회: WHERE user_id=42 AND created_at >= '2026-12-01' AND status='paid'
-- 나쁨: (user_id, created_at, status) — created_at 범위 뒤의 status는 못 탐
-- 좋음: (user_id, status, created_at) — 등호 둘 먼저, 범위 마지막

created_at을 범위로 쓰면서 중간에 두면, 그 뒤 status는 인덱스로 좁히지 못하고 걸러내기만 합니다.

카디널리티로 순서 다듬기

카디널리티(고유값 수)가 높은 컬럼을 앞에 두면 더 적은 행으로 빨리 좁혀집니다. 단, 위의 "선두 컬럼/등호 우선" 규칙이 먼저고, 그 안에서 카디널리티를 따집니다.

SQL
SELECT
  COUNT(DISTINCT user_id) AS u,    -- 높음 (수십만)
  COUNT(DISTINCT status)  AS s     -- 낮음 (3~4개)
FROM orders;

status처럼 값이 몇 개뿐인 컬럼을 단독·선두로 인덱싱하면 절반 이상을 읽게 돼 효과가 작습니다.

커버링 인덱스로 한 단계 더

조회하는 컬럼까지 인덱스에 다 들어 있으면 테이블 본체를 안 읽고 인덱스만으로 끝납니다. EXPLAIN ExtraUsing index가 뜹니다.

SQL
-- SELECT status, created_at WHERE user_id=42
-- 인덱스 (user_id, status, created_at) 면 테이블 접근 없이 해결

설계 체크리스트

SQL
EXPLAIN SELECT ...;          -- key가 의도한 인덱스인가, Extra=Using index인가
SHOW INDEX FROM orders;      -- Cardinality 컬럼 확인
-- WHERE의 등호 컬럼이 선두에 모여 있는가
-- 범위 조건 컬럼이 맨 뒤인가
-- ORDER BY 컬럼이 인덱스 순서와 맞는가

인덱스 순서를 바꿔가며 EXPLAIN으로 실행계획 변화를 직접 확인하는 실습은 데이터베이스 트랙에서 회원가입 없이 무료로 할 수 있습니다.