복합 인덱스의 컬럼 순서는 단순히 카디널리티가 높은 컬럼부터 배치하는 것이 아니라, 실제 쿼리의 WHERE, 조인, 정렬과 그룹화 패턴을 기준으로 결정해야 합니다.
MySQL의 (a, b, c) 인덱스는 기본적으로 왼쪽부터 이어지는 (a), (a, b), (a, b, c) 조건에 사용할 수 있습니다. 이를 Leftmost Prefix 원칙이라고 합니다. a 없이 b나 (b, c)만 사용하는 쿼리에서는 일반적인 인덱스 탐색에 활용하기 어렵습니다.
보통 다음 순서로 검토합니다.
- 여러 쿼리에서 공통으로 사용되고 데이터 접근 범위를 결정하는 컬럼을 앞에 둡니다.
- 동등 조건인
=또는IN컬럼을 범위 조건 컬럼보다 앞에 둡니다. - 첫 범위 조건 이후 컬럼은 탐색 범위를 좁히는 데 제한적으로 사용될 수 있으므로
ORDER BY와GROUP BY까지 고려합니다. - 필요한 경우 SELECT 컬럼을 뒤에 추가해 커버링 인덱스로 만들되 인덱스 크기와 쓰기 비용을 확인합니다.
예를 들어 WHERE tenant_id = ? AND status = ? AND created_at >= ? ORDER BY created_at 쿼리가 핵심이라면 (tenant_id, status, created_at)을 우선 검토할 수 있습니다. 최종 결정은 데이터 분포와 실제 실행 계획으로 검증해야 합니다.
SQL의 WHERE 절에 작성한 조건 순서가 인덱스 사용 순서를 결정하나요?
아닙니다. 옵티마이저가 조건을 분석하므로 SQL에 조건을 적은 순서보다 인덱스 정의의 컬럼 순서와 연산 종류가 중요합니다. 단, 가독성을 위해 쿼리 조건을 인덱스 순서와 비슷하게 작성할 수는 있습니다.
카디널리티가 높은 컬럼을 항상 첫 번째에 두어야 하나요?
아닙니다. 선택도는 중요하지만 쿼리에서 선두 컬럼을 사용하지 않으면 Leftmost Prefix를 활용하기 어렵습니다. 멀티 테넌트의
tenant_id처럼 단독 선택도는 낮더라도 거의 모든 쿼리의 접근 범위를 먼저 제한하는 컬럼이 선두에 적합할 수 있습니다.
단일 인덱스 여러 개와 복합 인덱스 하나는 같은가요?
같지 않습니다. 옵티마이저가 Index Merge를 사용할 수는 있지만 항상 복합 인덱스만큼 효율적인 것은 아니며 정렬까지 해결하지 못할 수 있습니다. 함께 사용되는 조건이 명확하다면 그 쿼리에 맞춘 복합 인덱스를 검토해야 합니다.