IT Knowledge/Database/images/인덱싱-전략-diagram.svg

데이터베이스 인덱싱 전략

📌 핵심 개념

인덱스는 책의 색인처럼 데이터를 빠르게 찾기 위한 자료구조

🎯 실전 사례

사례 1: 느린 쿼리 개선

Before: 인덱스 없음 (10초)

-- 100만 건 테이블에서 이메일로 검색
SELECT * FROM users WHERE email = 'user@example.com';
-- Execution time: 10.5 seconds
-- Full table scan (100만 건 모두 검색)

After: 인덱스 추가 (0.01초)

-- 인덱스 생성
CREATE INDEX idx_users_email ON users(email);
 
-- 동일한 쿼리
SELECT * FROM users WHERE email = 'user@example.com';
-- Execution time: 0.01 seconds
-- Index seek (B-Tree로 즉시 찾음)

사례 2: 복합 인덱스

문제: 날짜 + 상태로 자주 검색

-- ❌ 비효율적 (인덱스 2개 사용)
CREATE INDEX idx_created_at ON orders(created_at);
CREATE INDEX idx_status ON orders(status);
 
SELECT * FROM orders
WHERE created_at >= '2024-01-01'
  AND status = 'COMPLETED';
-- 두 인덱스 중 하나만 사용됨
 
-- ✅ 복합 인덱스 (효율적)
CREATE INDEX idx_created_status ON orders(created_at, status);
 
SELECT * FROM orders
WHERE created_at >= '2024-01-01'
  AND status = 'COMPLETED';
-- 10배 빠름

사례 3: 커버링 인덱스

문제: 테이블 접근 비용

-- ❌ 인덱스만으로 부족 (테이블 접근 필요)
CREATE INDEX idx_user_email ON users(email);
 
SELECT id, email, name FROM users
WHERE email = 'user@example.com';
-- 1. 인덱스에서 id 찾기
-- 2. 테이블에서 name 가져오기 (추가 I/O)
 
-- ✅ 커버링 인덱스 (인덱스만으로 완결)
CREATE INDEX idx_user_email_name ON users(email, name);
 
SELECT id, email, name FROM users
WHERE email = 'user@example.com';
-- 인덱스만 읽고 끝 (더 빠름)

💡 인덱스 설계 원칙

1. 선택도가 높은 컬럼

-- ✅ Good: 선택도 높음
CREATE INDEX idx_email ON users(email);
-- 이메일은 거의 유일함
 
-- ❌ Bad: 선택도 낮음
CREATE INDEX idx_gender ON users(gender);
-- gender는 'M' 또는 'F' 두 값뿐 (비효율)

2. 복합 인덱스 컬럼 순서

-- 등호(=) 조건을 앞에, 범위(>, <) 조건을 뒤에
CREATE INDEX idx_status_created ON orders(status, created_at);
 
-- ✅ 효율적 (status = 먼저)
SELECT * FROM orders
WHERE status = 'PENDING'
  AND created_at > '2024-01-01';
 
-- ❌ 비효율적 (순서 반대)
SELECT * FROM orders
WHERE created_at > '2024-01-01'
  AND status = 'PENDING';

3. 인덱스 모니터링

-- 사용하지 않는 인덱스 찾기 (PostgreSQL)
SELECT
  schemaname,
  tablename,
  indexname,
  idx_scan as index_scans
FROM pg_stat_user_indexes
WHERE idx_scan = 0
  AND indexname NOT LIKE '%_pkey';
 
-- 인덱스 삭제
DROP INDEX idx_unused;

🔗 참고 자료