
Clustered Index (클러스터드 인덱스)
클러스터드 인덱스란, 테이블의 데이터 자체가 인덱스에 포함되어 있는 구조입니다.
즉, 리프 노드가 실제 레코드를 저장합니다.
InnoDB 스토리지 엔진에서는 항상 Primary Key가 클러스터드 인덱스가 됩니다.
만약 PK가 없으면, NOT NULL UNIQUE 제약 조건이 있는 첫 번째 컬럼이 선택되며, 없으면 내부적으로 6바이트 Row ID가 자동 생성되어 클러스터드 인덱스로 사용됩니다.
구조
B+ Tree 구조
├── Internal Node
│ ├── Key
│ └── Pointer
└── Leaf Node
└── 실제 데이터 (Row)
예제
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10, 2)
);
- 여기서 id는 클러스터드 인덱스입니다.
- SELECT * FROM products WHERE id = 5 쿼리는 바로 해당 데이터 위치로 점프해서 결과를 가져옵니다.
- 데이터가 B+ Tree의 순서대로 물리적으로 정렬되어 저장되기 때문에 **범위 검색(range scan)**이 빠릅니다.
장점
- 빠른 PK 검색 속도
- 범위 조건 (BETWEEN, >=, <=)에 유리
- 리프 노드에 데이터가 있어 Back to Table 불필요
단점
- PK 기준으로 테이블이 정렬되므로, PK 변경이나 레코드 이동 시 I/O 부담
- Secondary Index가 리프 노드에 PK 값을 저장하므로, PK 길이가 길면 보조 인덱스도 커짐
Secondary Index (보조 인덱스)
Secondary Index는 클러스터드 인덱스가 아닌 일반 인덱스로, 리프 노드에 PK 값을 포함하고 있습니다.
즉, 보조 인덱스를 통해 값을 찾은 후, 클러스터드 인덱스를 다시 참조(Back to Table) 해야 실제 데이터를 가져올 수 있습니다.
구조
B+ Tree 구조
├── Internal Node
│ ├── Key (예: name)
│ └── Pointer
└── Leaf Node
├── Key (name)
└── PK 값 (예: id)
예제
CREATE INDEX idx_name ON products(name);
- 쿼리: SELECT * FROM products WHERE name = '샴푸';
- 동작:
- idx_name 보조 인덱스를 통해 '샴푸'에 해당하는 id 검색
- PK로 클러스터드 인덱스를 조회하여 실제 row 읽기 (Back to Table 발생)
장점
- PK 외 컬럼으로도 빠른 검색 가능
- 여러 보조 인덱스를 생성해 다양한 조건에 대응 가능
단점
- 항상 PK를 통해 다시 테이블에 접근하므로 추가 I/O 발생
- 복잡한 조건이나 정렬이 걸리면 성능 저하 가능
Covering Index (커버링 인덱스)
Covering Index란, 쿼리에 필요한 모든 컬럼이 인덱스에 포함되어 있어 테이블 접근 없이 쿼리를 처리할 수 있는 인덱스입니다.
즉, Back to Table 없이 인덱스만으로 쿼리를 커버할 수 있기 때문에 가장 빠른 형태의 조회입니다.
구조
보조 인덱스 내 리프 노드가 쿼리 대상 컬럼 전체를 포함
└── Leaf Node
├── name
├── price
└── PK (id)
예제
CREATE INDEX idx_name_price ON products(name, price);
-- covering index 사용 가능
SELECT name, price FROM products WHERE name = '샴푸';
- 쿼리에 사용된 모든 컬럼(name, price)이 인덱스에 있으므로, 테이블 접근 없이 인덱스만 읽고 결과 반환 가능
장점
- Back to Table 회피로 인한 성능 극대화
- 디스크 I/O 감소 → 빠른 처리 속도
주의할 점
- SELECT 대상 컬럼이 인덱스에 모두 포함되어야 함
- 인덱스 크기가 커질 수 있음 → 인덱스 관리 비용 증가
- 인덱스에 너무 많은 컬럼을 넣으면 오히려 비효율적

구분 | 저장 위치 | 리프 노드 내용 | Back to Table | 장점 |
Clustered Index | 테이블 자체 | 실제 데이터 전체 | ❌ | 가장 빠름, 정렬되어 있음 |
Secondary Index | 별도 인덱스 구조 | 인덱스 키 + PK | ⭕ | 여러 조건 대응 |
Covering Index | 보조 인덱스 중 일부 | 인덱스 키 + 모든 SELECT 컬럼 + PK | ❌ | 가장 효율적 조회, I/O 최소화 |