728x90
반응형
SMALL

저번 포스팅 주제에 이어
단순히 "인덱스를 걸자" 수준을 넘어서서, 인덱스를 설계하고, 유지하고, 실제로 활용하는 방법까지 실전 사례 기반으로 정리하려고 합니다.
그럼 포스팅 시작하겠습니다
복합 인덱스 vs 단일 인덱스
단일 인덱스:
CREATE INDEX idx_user_id ON orders(user_id);
복합 인덱스:
CREATE INDEX idx_user_date ON orders(user_id, order_date);
언제 복합 인덱스를 써야 하나요?
- 쿼리가 WHERE user_id = ? AND order_date >= ? 형태일 때
- 두 컬럼 모두 자주 조건절에 쓰일 때
실수 사례!!
-- 인덱스 (user_id, order_date) 존재 시
WHERE order_date = '2024-01-01' -- ❌ 인덱스 못탐
WHERE user_id = 1 -- ⭕ 인덱스 탐
WHERE user_id = 1 AND order_date = '2024-01-01' -- ⭕ 인덱스 탐
왼쪽 컬럼부터 차례대로 사용해야 인덱스가 작동합니다. 이것을 Left-most Prefix Rule이라고 합니다.
커버링 인덱스 (Covering Index)
쿼리에서 필요한 모든 컬럼이 인덱스에 포함되어 있는 경우 → 테이블 자체를 읽지 않고 인덱스만으로 결과 반환
CREATE INDEX idx_covering ON orders(user_id, status, order_date);
-- 해당 인덱스가 커버링 인덱스 역할
SELECT status FROM orders WHERE user_id = 123 AND order_date >= '2024-01-01';
장점:
- 디스크 I/O 최소화
- 성능 극대화
인덱스가 안 먹히는 쿼리 패턴들
❌ 함수 사용
WHERE DATE(created_at) = '2025-08-01' -- 인덱스 못탐
함수가 들어간 컬럼은 인덱스 범위를 타지 못합니다.
✅ 대안
WHERE created_at BETWEEN '2025-08-01' AND '2025-08-01 23:59:59'
정렬을 빠르게 하고 싶다면?
-- created_at에 인덱스가 없으면 정렬 느림
SELECT * FROM logs ORDER BY created_at DESC LIMIT 10;
정렬이 잦은 컬럼은 반드시 인덱스 필요
CREATE INDEX idx_created_at_desc ON logs(created_at DESC);
※ PostgreSQL은 DESC 인덱스를 따로 설정해야 효율적입니다.
불필요한 인덱스는 성능을 해친다
- 쓰기 성능 저하: INSERT/UPDATE/DELETE 할 때마다 모든 인덱스 갱신됨
- 디스크 공간 낭비
- 옵티마이저 혼란: 인덱스가 많으면 최적의 경로를 선택하지 못할 수도 있음
💡 점검 방법
-- 인덱스 통계 확인 (PostgreSQL 기준)
SELECT * FROM pg_stat_user_indexes WHERE idx_scan = 0;
인덱스 힌트 사용 (MySQL 기준)
때론 옵티마이저가 인덱스를 안 타는 경우, 강제로 타게 하기
SELECT * FROM orders USE INDEX (idx_user_date)
WHERE user_id = 1 AND order_date > '2024-01-01';
EXPLAIN 제대로 해석하기
EXPLAIN SELECT * FROM orders WHERE user_id = 1;
주요 항목 해석:
|
항목
|
의미
|
|
type
|
ALL, index, range, ref, const 등 (좋을수록 정교함)
|
|
key
|
사용된 인덱스 이름
|
|
rows
|
스캔할 예상 행 수
|
|
Extra
|
Using where / Using index / Using temporary 등
|
목표: type = range/ref, Using index 가 나오도록 쿼리 개선
인덱스 재구성 (Rebuild)
- 데이터가 많이 바뀐 경우, 인덱스가 비효율적일 수 있음
- PostgreSQL: REINDEX TABLE your_table;
- MySQL: OPTIMIZE TABLE your_table;
마무리 요약
|
전략
|
핵심 요점
|
|
복합 인덱스
|
Left-most Rule, 조합 순서 중요
|
|
커버링 인덱스
|
SELECT 대상도 인덱스에 포함되면 테이블 접근 없이 조회 가능
|
|
함수 사용 금지
|
WHERE절에서 컬럼에 함수 쓰면 인덱스 무효화됨
|
|
정렬 최적화
|
ORDER BY 컬럼에 인덱스 구성 필요
|
|
과도한 인덱스 제거
|
조회 빈도 낮은 인덱스는 오히려 성능 저하
|
|
EXPLAIN 확인
|
옵티마이저가 어떤 방식으로 테이블 접근하는지 확인 필요
|
|
인덱스 힌트
|
옵티마이저가 인덱스 안 타면 강제로 타게 설정 가능
|
#SQL성능 #DB인덱스 #쿼리튜닝 #실무SQL #PostgreSQL #MySQL #커버링인덱스 #java공부 #백엔드개발 #데이터최적화
728x90
반응형
LIST
'TIPS' 카테고리의 다른 글
| 다양한 x + JOIN 차이 언제 어떤 걸 써야 할까? (6) | 2025.08.25 |
|---|---|
| WHERE vs HAVING의 차이 – 언제 어떤 걸 써야 할까? (4) | 2025.08.18 |
| 실무에서 바로 써먹는 SQL 쿼리 성능 개선 팁 (10) | 2025.08.04 |
| 실무에서 자주 쓰이지만 까다로운 SQL 문법 정리 (8) | 2025.07.28 |
| Spark 실전 성능 튜닝 #Executor, #Shuffle, #GC (4) | 2025.07.21 |