- 0
- 276 단어
복합 인덱스는 데이터베이스에서 두 개 이상의 컬럼을 하나의 인덱스로 묶어 사용하는 방식입니다. 하나의 컬럼만 검색하는 단일 인덱스와 달리 여러 컬럼을 함께 조건으로 사용하는 SQL의 검색 성능을 개선하기 위해 활용합니다. 복합 인덱스는 여러 컬럼을 하나의 구조로 관리한다는 점에서 단순한 인덱스와 차이가 있으며, 특히 인덱스를 구성하는 컬럼의 순서가 중요합니다.
복합 인덱스의 기본 개념
먼저 하나의 컬럼에만 인덱스를 생성하는 경우를 생각해볼 수 있습니다.
CREATE INDEX idx_users_name
ON users(name);
이 인덱스는 name 컬럼을 기준으로 데이터를 검색할 때 활용할 수 있습니다.
하지만 실제 서비스에서는 하나의 조건만 사용하는 검색보다 여러 조건을 함께 사용하는 검색이 자주 발생합니다. 예를 들어 쇼핑몰의 주문 테이블에서 특정 사용자의 주문을 특정 날짜 범위로 조회한다고 가정할 수 있습니다.
SELECT *
FROM orders
WHERE user_id = 1001
AND order_date >= '2026-01-01'
AND order_date < '2026-02-01';
이러한 SQL에서는 user_id와 order_date를 함께 사용하는 조건이 존재합니다.
이때 다음과 같이 두 컬럼을 하나의 인덱스로 묶을 수 있습니다.
CREATE INDEX idx_orders_user_date
ON orders(user_id, order_date);
이처럼 여러 컬럼을 하나의 인덱스로 구성한 것을 **복합 인덱스(Composite Index)**라고 합니다.
복합 인덱스는 여러 개의 인덱스를 단순히 따로 만드는 것과는 다릅니다.
단일 인덱스
user_id → 인덱스 1
order_date → 인덱스 2
복합 인덱스
user_id + order_date
↓
하나의 인덱스 구조
따라서 여러 컬럼을 함께 검색하는 SQL이 많은 경우 복합 인덱스를 적절하게 설계하면 검색 범위를 효율적으로 줄일 수 있습니다.
복합 인덱스에서 컬럼 순서가 중요한 이유
복합 인덱스에서 가장 중요한 특징 중 하나는 컬럼을 어떤 순서로 배치하느냐에 따라 인덱스 활용 방식이 달라질 수 있다는 점입니다.
예를 들어 다음과 같은 복합 인덱스를 생성했다고 가정합니다.
CREATE INDEX idx_orders_user_date
ON orders(user_id, order_date);
이 인덱스는 개념적으로 user_id를 먼저 정렬한 다음 같은 user_id 안에서 order_date를 정렬하는 구조로 생각할 수 있습니다.
user_id | order_date
--------|------------
1001 | 2026-01-01
1001 | 2026-01-05
1001 | 2026-01-20
1002 | 2026-01-03
1002 | 2026-01-15
1003 | 2026-01-02
1003 | 2026-02-10
먼저 user_id를 기준으로 범위를 찾고, 그 안에서 order_date를 이용하여 다시 범위를 좁힐 수 있는 형태입니다.
따라서 다음과 같은 SQL은 복합 인덱스의 구조와 잘 맞을 수 있습니다.
SELECT *
FROM orders
WHERE user_id = 1001
AND order_date >= '2026-01-01'
AND order_date < '2026-02-01';
먼저 user_id = 1001인 영역을 찾은 다음 해당 영역에서 날짜 조건을 적용하는 방식으로 검색 범위를 줄일 수 있습니다.
반대로 다음과 같이 order_date만 조건으로 사용하는 경우에는 주의가 필요합니다.
SELECT *
FROM orders
WHERE order_date >= '2026-01-01'
AND order_date < '2026-02-01';
현재 복합 인덱스가 (user_id, order_date) 순서라면 인덱스의 첫 번째 컬럼인 user_id를 사용하지 않고 두 번째 컬럼인 order_date만 조건으로 사용하고 있습니다. 이 경우 일반적인 B-Tree 복합 인덱스의 정렬 특성상 order_date만으로 원하는 범위를 효율적으로 찾기 어려울 수 있습니다.
이를 **선두 컬럼(Leading Column)**과 관련된 특성으로 이해할 수 있습니다.
즉,
(user_id, order_date)
1번째 컬럼 → user_id
2번째 컬럼 → order_date
복합 인덱스를 사용할 때는 앞쪽에 위치한 컬럼이 중요한 역할을 합니다.
따라서 다음 두 인덱스는 서로 동일하지 않습니다.
CREATE INDEX idx1
ON orders(user_id, order_date);
CREATE INDEX idx2
ON orders(order_date, user_id);
두 인덱스 모두 user_id와 order_date를 포함하지만 컬럼 순서가 다르기 때문에 인덱스가 구성되는 방식과 효율적으로 활용할 수 있는 검색 조건이 달라질 수 있습니다.
복합 인덱스의 활용 예시
복합 인덱스는 여러 조건을 자주 사용하는 서비스에서 유용하게 사용할 수 있습니다.
예를 들어 상품 테이블에서 category_id와 price를 기준으로 상품을 검색한다고 가정합니다.
SELECT *
FROM products
WHERE category_id = 10
AND price >= 50000;
이러한 검색이 자주 발생한다면 다음과 같은 복합 인덱스를 고려할 수 있습니다.
CREATE INDEX idx_products_category_price
ON products(category_id, price);
이 경우 데이터베이스는 먼저 category_id를 기준으로 검색 범위를 좁힌 뒤 해당 범위에서 price 조건을 처리할 수 있습니다.
또 다른 예로 게시판에서 특정 사용자의 글을 최신 작성 순서로 조회하는 상황을 생각할 수 있습니다.
SELECT *
FROM posts
WHERE user_id = 1001
ORDER BY created_at DESC;
이러한 조회가 반복된다면 다음과 같은 인덱스를 고려할 수 있습니다.
CREATE INDEX idx_posts_user_created
ON posts(user_id, created_at);
이처럼 복합 인덱스는 단순히 WHERE 조건만을 위한 것이 아니라 검색 조건과 정렬 방식까지 함께 고려하여 설계할 수 있습니다. 다만 실제로 ORDER BY까지 인덱스를 효과적으로 활용할 수 있는지는 데이터베이스의 실행 계획과 조건에 따라 달라질 수 있으므로 EXPLAIN 등을 이용해 확인해야 합니다.
복합 인덱스를 무조건 많이 만들면 안 되는 이유
복합 인덱스는 검색 성능을 개선할 수 있지만 여러 개의 인덱스를 무조건 생성하는 것은 적절하지 않습니다.
예를 들어 다음과 같이 여러 인덱스를 만들 수 있습니다.
CREATE INDEX idx_user
ON orders(user_id);
CREATE INDEX idx_date
ON orders(order_date);
CREATE INDEX idx_user_date
ON orders(user_id, order_date);
이렇게 하면 다양한 검색 조건에 대응할 수 있지만 인덱스가 많아질수록 저장 공간도 증가하고 데이터가 변경될 때 관리해야 하는 인덱스도 많아집니다.
INSERT, UPDATE, DELETE가 발생하면 테이블의 데이터뿐만 아니라 관련 인덱스도 변경해야 합니다. 따라서 조회가 빨라지는 효과만 생각할 것이 아니라 데이터 변경에 발생하는 비용까지 고려해야 합니다.
또한 이미 존재하는 인덱스와 역할이 겹치는 인덱스를 불필요하게 생성하면 관리해야 할 구조만 늘어날 수 있습니다.
복합 인덱스를 설계할 때는 다음과 같은 사항을 함께 확인하는 것이 중요합니다.
1. 어떤 검색 조건을 자주 사용하는가?
2. 여러 컬럼을 함께 검색하는가?
3. 컬럼의 순서는 적절한가?
4. 정렬 조건과 함께 활용할 수 있는가?
5. 기존 인덱스와 역할이 겹치지 않는가?
6. INSERT, UPDATE, DELETE가 많은 테이블은 아닌가?
7. EXPLAIN을 통해 실제 실행 계획을 확인했는가?
결국 복합 인덱스의 핵심은 여러 컬럼을 하나로 묶는 것 자체가 아니라 실제 조회 패턴에 맞는 순서로 인덱스를 설계하는 것입니다.
특히 (A, B) 형태의 복합 인덱스가 있다고 해서 A와 B를 사용하는 모든 검색에서 동일하게 효과가 발생하는 것은 아닙니다. 인덱스의 선두 컬럼과 검색 조건의 관계를 이해해야 하며, 실제 데이터와 SQL을 기준으로 실행 계획을 확인해야 합니다.
복합 인덱스를 적절하게 사용하면 대량의 데이터에서 여러 조건을 사용하는 검색을 효율적으로 처리하는 데 도움을 줄 수 있습니다. 반면 잘못된 컬럼 순서나 불필요한 인덱스는 기대한 성능 향상을 얻지 못하면서 저장 공간과 데이터 변경 비용만 증가시킬 수 있습니다.
다음 단계에서는 데이터베이스에서 중요한 설계 개념 중 하나인 정규화를 살펴볼 수 있습니다. 정규화는 하나의 테이블에 모든 데이터를 저장하는 대신 데이터의 중복을 줄이고 데이터의 일관성을 유지하기 위해 테이블을 적절한 구조로 나누는 방법입니다.