Learning
레슨 5 / 8·20분

인덱스와 쿼리 최적화

인덱스(Index)란?

인덱스는 테이블의 데이터를 빠르게 검색하기 위한 자료구조입니다. 책의 색인처럼, 인덱스를 사용하면 전체 테이블을 스캔하지 않고도 원하는 데이터를 찾을 수 있습니다. 대부분의 RDBMS는 B-Tree 인덱스를 기본으로 사용합니다.

인덱스 생성과 관리

sql
-- 단일 열 인덱스
CREATE INDEX idx_employees_name
ON employees (name);

-- 복합 인덱스 (여러 열)
CREATE INDEX idx_emp_dept_salary
ON employees (department, salary);

-- 유니크 인덱스 (중복 불허)
CREATE UNIQUE INDEX idx_employees_email
ON employees (email);

-- 인덱스 확인
SHOW INDEX FROM employees;

-- 인덱스 삭제
DROP INDEX idx_employees_name ON employees;

EXPLAIN으로 쿼리 실행 계획 분석

sql
-- 실행 계획 확인
EXPLAIN SELECT * FROM employees
WHERE department = '개발팀'
  AND salary > 50000;

-- 결과 해석:
-- type: ALL (풀 테이블 스캔) -> 인덱스 필요
-- type: ref (인덱스 사용) -> 양호
-- type: range (인덱스 범위 스캔) -> 양호
-- rows: 스캔할 예상 행 수 (적을수록 좋음)

-- 인덱스 추가 후 다시 확인
CREATE INDEX idx_dept_salary ON employees (department, salary);

EXPLAIN SELECT * FROM employees
WHERE department = '개발팀'
  AND salary > 50000;
-- type이 ref 또는 range로 변경됨

쿼리 최적화 기법

sql
-- 1. SELECT * 대신 필요한 열만 조회
-- 나쁜 예
SELECT * FROM employees WHERE department = '개발팀';
-- 좋은 예
SELECT name, salary FROM employees WHERE department = '개발팀';

-- 2. LIKE에서 앞쪽 와일드카드 피하기
-- 나쁜 예 (인덱스 사용 불가)
SELECT * FROM employees WHERE name LIKE '%철수';
-- 좋은 예 (인덱스 사용 가능)
SELECT * FROM employees WHERE name LIKE '김%';

-- 3. 서브쿼리 대신 JOIN 사용
-- 느린 서브쿼리
SELECT * FROM employees
WHERE department_id IN (
    SELECT id FROM departments WHERE location = '서울'
);
-- 빠른 JOIN
SELECT e.* FROM employees e
INNER JOIN departments d ON e.department_id = d.id
WHERE d.location = '서울';

-- 4. EXISTS vs IN (대량 데이터)
SELECT * FROM employees e
WHERE EXISTS (
    SELECT 1 FROM departments d
    WHERE d.id = e.department_id
      AND d.location = '서울'
);
  • PRIMARY KEY는 자동으로 인덱스가 생성됨
  • WHERE, JOIN, ORDER BY에 자주 사용되는 열에 인덱스 생성
  • 복합 인덱스는 왼쪽 열부터 순서대로 활용됨 (Leftmost Prefix)
  • 인덱스가 많으면 INSERT/UPDATE 성능이 저하됨
  • EXPLAIN으로 실행 계획을 확인하고 최적화할 것
💡

인덱스는 읽기(SELECT) 성능을 높이지만 쓰기(INSERT/UPDATE/DELETE) 성능을 낮춥니다. 읽기가 많은 테이블에는 인덱스를 적극 활용하고, 쓰기가 많은 테이블은 최소한의 인덱스만 유지하세요.