💻데브노트소개
🗄️

SQL 인덱스 원리와 튜닝: 느린 쿼리를 빠르게 만드는 법

데브노트 편집팀·2026.07.02·8분 읽기
X(트위터)
ADVERTISEMENT

"인덱스 걸었는데 왜 안 빨라지죠?" 실무에서 정말 자주 나오는 질문입니다. 인덱스는 마법이 아니라 **정렬된 색인(목차)**입니다. 책 뒤 찾아보기처럼, 원리를 알아야 제대로 씁니다. 대부분의 RDB 인덱스는 B-Tree 구조로, 값이 정렬되어 있어 범위 검색과 정렬에 강합니다.

1. 인덱스는 언제 효과가 있나

-- email로 자주 조회한다면
CREATE INDEX idx_users_email ON users (email);

-- 실행 계획 확인 (인덱스 타는지 확인 필수)
EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';

핵심: EXPLAIN으로 실제 인덱스를 타는지(type: ref 등) 반드시 확인하세요. 안 보고 추측하면 안 됩니다.

2. 복합 인덱스와 좌측 우선 규칙

(a, b, c) 순서로 만든 인덱스는 왼쪽부터 연속으로만 활용됩니다.

WHERE 조건인덱스 사용
a = ?O
a = ? AND b = ?O
b = ? 단독X (좌측 a 건너뜀)
a = ? AND c = ?a까지만
CREATE INDEX idx_orders ON orders (user_id, status, created_at);
-- 잘 탐: WHERE user_id = 5 AND status = 'PAID'
-- 못 탐: WHERE status = 'PAID'  (user_id 없이 status만)

컬럼 순서 규칙: 등호(=) 조건 컬럼을 앞에, 범위(>, <) 조건은 뒤에 두고, 같은 등호끼리는 카디널리티(중복 적은 값)가 높은 컬럼을 앞에 둡니다.

3. 인덱스를 무력화하는 안티패턴

-- 나쁨: 컬럼을 가공하면 인덱스 못 씀
SELECT * FROM users WHERE YEAR(created_at) = 2026;

-- 좋음: 컬럼은 그대로, 값 쪽을 가공
SELECT * FROM users
WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01';

주의: LIKE '%검색%'(앞에 와일드카드), OR 남발, 컬럼에 함수/연산 적용은 인덱스를 무력화합니다.

4. 커버링 인덱스로 한 단계 더

쿼리가 필요로 하는 컬럼을 인덱스에 모두 포함하면, 테이블 접근 없이 인덱스만 읽고 끝(index-only scan)나서 가장 빠릅니다.

-- user_id로 조회해 status, created_at만 본다면
CREATE INDEX idx_cover ON orders (user_id, status, created_at);
SELECT status, created_at FROM orders WHERE user_id = 5;

마무리 체크리스트

  • 튜닝 전후 EXPLAIN으로 검증
  • 복합 인덱스는 좌측 우선, 등호→범위 순서
  • WHERE 컬럼에 함수/연산 금지
  • 선두 % LIKE 피하기
  • 인덱스도 쓰기 비용이 있으니 무분별하게 늘리지 말 것
#SQL#인덱스#DB튜닝#성능최적화
X(트위터)
ADVERTISEMENT