1. 복합 인덱스(Composite Index)란?
- 복합 인덱스는 두 개 이상의 컬럼을 결합하여 생성한 인덱스입니다.
- MySQL에서는 최대 16개의 컬럼을 하나의 인덱스로 결합할 수 있습니다.
- 단일 복합 인덱스로 여러 유형의 쿼리 성능을 향상시킬 수 있습니다.
- 인덱스에 포함된 컬럼들의 순서가 쿼리 성능에 중요한 영향을 미칩니다.
2. 복합 인덱스의 작동 원리
- 복합 인덱스는 지정된 컬럼들의 값을 연결하여 정렬된 데이터 구조를 생성합니다.
- MySQL은 이 정렬된 구조를 활용하여 쿼리를 더 빠르게 실행합니다.
- 복합 인덱스는 다음 경우에 활용됩니다:
- 인덱스의 모든 컬럼을 테스트하는 쿼리
- 첫 번째 컬럼만 테스트하는 쿼리
- 첫 번째와 두 번째 컬럼을 테스트하는 쿼리
- 인덱스의 좌측부터 연속된 컬럼들을 테스트하는 쿼리
2.1 복합 인덱스의 내부 구 조
- 복합 인덱스는 B-트리 구조로 구현되어 있습니다.
- 인덱스 노드는 복합 키(여러 컬럼 값의 조합)를 기준으로 정렬됩니다.
- 이 구조는 범위 검색과 정확한 일치 검색 모두에 효율적입니다.
팁
복합 인덱스의 컬럼 순서는 성능에 큰 영향을 미칩니다. 일반적으로 선택성(selectivity)이 높은 컬럼(고유한 값이 많은 컬럼)을 인덱스의 앞쪽에 배치하는 것이 좋습니다. Selectivity Cardinality 참고
3. 복합 인덱스 사용 규칙
3.1 좌측 접두사 규칙(Leftmost Prefix Rule)
- 복합 인덱스의 가장 중요한 특성은 좌측 접두사 규칙입니다.
- MySQL은 인덱스의 왼쪽부터 시작하는 컬럼들만 사용할 수 있으며, 중간 컬럼을 건너뛸 수 없습니다.
- 예를 들어,
(col1, col2, col3)인덱스가 있다면:col1만 조건으로 사용하는 쿼리에 활용 가능col1, col2를 조건으로 사용하는 쿼리에 활용 가능col1, col2, col3모두를 조건으로 사용하는 쿼리에 활용 가능col2만 또는col2, col3만 조건으로 사용하는 쿼리에는 활용 불가
경고
복합 인덱스에서 첫 번째 컬럼(좌측 컬럼)을 조건에 포함하지 않으면 해당 인덱스는 사용되지 않습니다. 이 규칙을 이해하는 것이 복합 인덱스 설계의 핵심입니다.
좌측 접두사 예시
(last_name, first_name)으로 구성된 복합 인덱스가 있을 때:WHERE last_name = 'Kim'→ 인덱스 사용 가능WHERE last_name = 'Kim' AND first_name = 'Minho'→ 인덱스 사용 가능WHERE first_name = 'Minho'→ 인덱스 사용 불가
3.2 첫 번째 범위 조건 이후 규칙
- MySQL은 복합 인덱스에서 첫 번째 범위 조건(
>,<,BETWEEN등) 이후의 컬럼은 인덱스 스캔에 활용하지 않습니다. - 범위 조건은 다음 컬럼의 정렬 순서를 깨뜨리기 때문입니다.
- 예를 들어,
(first_name, last_name, birthday)인덱스가 있을 때:WHERE first_name = 'Aaron' AND last_name = 'Francis' AND birthday = '1989-02-14'→ 모든 컬럼 인덱스 사용WHERE first_name = 'Aaron' AND last_name < 'Francis' AND birthday = '1989-02-14'→first_name과last_name만 인덱스 사용,birthday는 인덱스 사용 불가
정보
이 두 가지 규칙(좌측 접두사 규칙과 첫 번째 범위 조건 이후 규칙)이 복합 인덱스 사용의 핵심입니다. 이를 이해하면 복합 인덱스를 효과적으로 활용할 수 있습니다.
4. 복합 인덱스 실전 예제
4.1 테이블 구조 및 인덱스 생성
-- 단일 컬럼 인덱스 생성
ALTER TABLE people
ADD INDEX first_name (first_name);
ALTER TABLE people
ADD INDEX last_name (last_name);
ALTER TABLE people
ADD INDEX birthday (birthday);
-- 복합 인덱스 생성
ALTER TABLE people
ADD INDEX multi (first_name, last_name, birthday);
복합 인덱스를 생성한 후, SHOW INDEXES 명령을 통해 인덱스 구조를 확인할 수 있습니다:
SHOW
INDEXES FROM people;
결과:
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Index_type |
|--------|------------|----------|--------------|-------------|-----------|-------------|------------|
| people | 1 | multi | 1 | first_name | A | 3107 | BTREE |
| people | 1 | multi | 2 | last_name | A | 419540 | BTREE |
| people | 1 | multi | 3 | birthday | A | 491583 | BTREE |
여기서 Seq_in_index 열은 복합 인덱스 내의 컬럼 순서를 나타냅니다. 이 순서는 인덱스 사용 방식에 중요한 영향을 미칩니다.
4.2 EXPLAIN을 통한 인덱스 사용 분석
MySQL에서는 EXPLAIN 명령을 사용하여 쿼리가 인덱스를 어떻게 활용하는지 분석할 수 있습니다.
4.2.1 모든 컬 럼에 대한 동등 조건
EXPLAIN
SELECT *
FROM people
WHERE first_name = 'Aaron'
AND last_name = 'Francis';
결과:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered |
|----|-------------|--------|------|---------------|-------|---------|-------------|------|----------|
| 1 | SIMPLE | people | ref | multi | multi | 404 | const,const | 1 | 100.00 |
key_len 값이 404바이트인 것은 MySQL이 first_name과 last_name 두 컬럼을 모두 인덱스로 사용하고 있음을 나타냅니다.
EXPLAIN
SELECT *
FROM people
WHERE first_name = 'Aaron'
AND last_name = 'Francis'
AND birthday = '1989-02-14';
결과:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered |
|----|-------------|--------|------|---------------|-------|---------|-------------------|------|----------|
| 1 | SIMPLE | people | ref | multi | multi | 407 | const,const,const | 1 | 100.00 |