MySQL 인덱스 완벽 가이드: 성능 최적화의 핵심
반응형
목차
인덱스란?
인덱스는 데이터베이스 테이블의 검색 성능을 향상시키기 위한 자료구조입니다. 책의 목차나 색인과 같이, 데이터를 빠르게 찾을 수 있도록 도와줍니다.
인덱스가 필요한 이유
-- 인덱스가 없는 경우: 전체 테이블 스캔
SELECT * FROM users WHERE email = 'user@example.com';
-- 인덱스가 있는 경우: 인덱스를 통한 빠른 검색
CREATE INDEX idx_email ON users(email);
SELECT * FROM users WHERE email = 'user@example.com';
인덱스의 종류
1. 클러스터형 인덱스 (Clustered Index)
- 테이블당 1개만 생성 가능
- 물리적으로 데이터를 정렬
- InnoDB에서는 기본적으로 PK가 클러스터형 인덱스
CREATE TABLE users (
id INT PRIMARY KEY, -- 클러스터형 인덱스
name VARCHAR(50),
email VARCHAR(100)
);
2. 보조 인덱스 (Secondary Index)
- 여러 개 생성 가능
- 데이터의 물리적 순서와 무관
- 인덱스 페이지와 데이터 페이지가 분리
-- 단일 컬럼 인덱스
CREATE INDEX idx_email ON users(email);
-- 복합 컬럼 인덱스
CREATE INDEX idx_name_email ON users(name, email);
3. 유니크 인덱스
CREATE UNIQUE INDEX idx_email ON users(email);
4. 전문 검색 인덱스 (Fulltext Index)
CREATE FULLTEXT INDEX idx_content ON articles(content);
인덱스 동작 원리
B-Tree 구조
[Root Node]
/ | \
[Node] [Node] [Node]
/ | / | / |
[Leaf][Leaf][Leaf][Leaf]
인덱스 스캔 과정
-- 인덱스 사용 예시
EXPLAIN SELECT * FROM users
WHERE email = 'user@example.com';
인덱스 설계 전략
1. 선택도(Selectivity) 고려
-- 높은 선택도 (좋은 예)
CREATE INDEX idx_email ON users(email); -- 이메일은 대부분 고유
-- 낮은 선택도 (나쁜 예)
CREATE INDEX idx_gender ON users(gender); -- 성별은 값의 종류가 적음
2. 복합 인덱스 순서
-- 좋은 예
CREATE INDEX idx_email_created_at ON users(email, created_at);
-- 나쁜 예
CREATE INDEX idx_created_at_email ON users(created_at, email);
3. 커버링 인덱스
-- 커버링 인덱스 활용
CREATE INDEX idx_name_email ON users(name, email);
SELECT name, email FROM users WHERE name = 'John'; -- 데이터 페이지 접근 불필요
실전 예제
1. 회원 검색 최적화
-- 테이블 구조
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(100),
name VARCHAR(50),
status ENUM('active', 'inactive'),
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- 효율적인 인덱스 설계
CREATE INDEX idx_email ON users(email);
CREATE INDEX idx_status_created_at ON users(status, created_at);
2. 주문 조회 시스템
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
order_status VARCHAR(20),
order_date TIMESTAMP,
total_amount DECIMAL(10,2)
);
-- 자주 사용되는 조회 패턴에 대한 인덱스
CREATE INDEX idx_user_date ON orders(user_id, order_date);
CREATE INDEX idx_status_date ON orders(order_status, order_date);
성능 분석
1. EXPLAIN 활용
EXPLAIN SELECT * FROM users
WHERE email = 'test@example.com'
AND created_at > '2024-01-01';
-- 결과 분석
-- type: ref/range/ALL 등을 확인
-- key: 사용된 인덱스 확인
-- rows: 스캔된 행 수 확인
2. 성능 측정
-- 쿼리 실행 시간 측정
SET profiling = 1;
SELECT * FROM users WHERE email = 'test@example.com';
SHOW PROFILES;
3. 인덱스 사용 통계
-- 인덱스 사용 통계 확인
SHOW INDEX FROM users;
주의사항
1. 과도한 인덱스 생성 피하기
-- 불필요한 인덱스 식별
SELECT * FROM information_schema.statistics
WHERE table_schema = 'your_database'
AND table_name = 'users';
-- 사용되지 않는 인덱스 제거
DROP INDEX idx_unused ON users;
2. INSERT/UPDATE 성능 고려
-- 대량 데이터 입력 시 임시로 인덱스 비활성화
ALTER TABLE users DISABLE KEYS;
-- 데이터 입력
ALTER TABLE users ENABLE KEYS;
3. 인덱스 관리
-- 인덱스 재구축
ANALYZE TABLE users;
OPTIMIZE TABLE users;
성능 최적화 사례
1. 로그인 조회 최적화
-- 변경 전
SELECT * FROM users WHERE email = ? AND status = 'active';
-- 변경 후
CREATE INDEX idx_email_status ON users(email, status);
2. 날짜 범위 검색 최적화
-- 변경 전
SELECT * FROM orders
WHERE created_at BETWEEN ? AND ?
AND status = 'completed';
-- 변경 후
CREATE INDEX idx_status_created ON orders(status, created_at);
모니터링과 유지보수
1. 인덱스 상태 모니터링
-- 인덱스 크기 확인
SELECT
table_name,
index_name,
stat_value as pages
FROM mysql.innodb_index_stats
WHERE stat_name = 'size'
AND database_name = 'your_database';
2. 미사용 인덱스 식별
SELECT * FROM sys.schema_unused_indexes;
3. 중복 인덱스 확인
SELECT
table_schema,
table_name,
COUNT(*) as index_count
FROM information_schema.statistics
GROUP BY table_schema, table_name
HAVING COUNT(*) > 1;
마치며
인덱스는 데이터베이스 성능 최적화의 핵심이지만, 무분별한 사용은 오히려 성능 저하를 초래할 수 있습니다. 적절한 인덱스 설계와 지속적인 모니터링이 중요합니다.
핵심 포인트
- 선택도가 높은 컬럼에 인덱스 생성
- 복합 인덱스 순서 최적화
- 커버링 인덱스 활용
- 정기적인 인덱스 관리
- 성능 모니터링
추천 자료
- MySQL 공식 문서
- Real MySQL (백은빈, 이성욱 저)
- High Performance MySQL
반응형
'CS' 카테고리의 다른 글
[OAuth] 회사 방문증으로 이해하는 인증 원리 (1) | 2024.11.13 |
---|---|
트랜잭션과 격리 수준 완벽 가이드 (0) | 2024.11.12 |
쿠키와 세션 (0) | 2024.09.03 |
왜 MVC 패턴을 사용하고 있나요? (5) | 2024.08.29 |
댓글