데이터베이스 쿼리의 실행 속도와 자원 사용량을 최적화하는 작업
성능을 좌우하는 핵심 요소들로, 잘 설계하면 성능이 좋아지고, 잘못 쓰면 성능이 나빠짐
불필요한 대량 데이터 조회를 막고, 필요한 만큼만 가져오기
조건을 명확히 줘서 불필요한 row를 피하도록 설계
간결하지만 중첩되면 느려짐, JOIN으로 바꾸면 나아짐
SQL 실행 계획 분석
| 항목 | 의미 |
|---|---|
id | SELECT 문에 대한 고유 ID |
select_type | 쿼리의 타입(SIMPLE, PRIMARY, SUBQUERY 등) |
table | 조회 대상 테이블 이름 |
type | 조인 방식 또는 접근 방식 |
possible_keys | 사용 가능한 인덱스 목록 |
key | 사용한 인덱스 |
key_len | 사용된 인덱스의 길이 (bytes) |
ref | 어떤 속성을 기준으로 인덱스가 사용되었는지 표시 |
rows | MySQL이 예측한 스캔할 행의 수 |
Extra | 추가 정보 |
각 단계별 실행 시간 분석
서버 상태 및 실행 통계 확인
MySQL 내부 성능 측정용 DB
오래 걸리는 쿼리 기록 (로그 기반 튜닝)
SET profiling = 1; # 프로파일링 기능을 켬
SHOW PROFILES; # 실행했던 SQL의 실행 시간 표시
SELECT * FROM member;
SHOW PROFILE FOR QUERY 6; # 특정 쿼리 상세 조회
EXPLAIN SELECT * FROM member; # SQL 실행 계획 표시
# SELECT 쿼리를 실행하기 전에 MySQL이 어떤 식으로 데이터를 가져올지를 보여줌
-- member 테이블 구조 확인
DESC member;
-- 쿼리 실행 예시 및 성능 확인
SELECT * FROM member;
테이블의 전체 데이터를 조회
인덱스 없이 전체 테이블을 순회하게 되므로 비효율적일 수 있음
EXPLAIN SELECT * FROM member WHERE idx=1;
idx는 AUTO_INCREMENT이므로 기본키(PK)로 설정되어 있을 가능성이 큼
이 쿼리는 PK 기반 단건 조회 → 매우 빠르고 효율적
EXPLAIN SELECT * FROM member WHERE email='test1';
email 컬럼에는 인덱스가 아직 없을 수도 있음
이 경우 type = ALL (전체 탐색)이 나오며 성능이 떨어짐
SELECT * FROM member WHERE idx=1;
SELECT * FROM member WHERE email='test1';
SELECT * FROM member WHERE idx=1128;
# 인덱스 생성하는 법
CREATE INDEX member_index_email ON member(email);
-- post 테이블 생성
CREATE TABLE post (
idx INT AUTO_INCREMENT PRIMARY KEY,
writerIdx INT,
contents VARCHAR(100),
createdAt DATETIME,
FOREIGN KEY (writerIdx) REFERENCES member(idx)
);
테이블 생성
데이터 삽입
EXPLAIN 및 PROFILE 로 SELECT 성능 체크
인덱스 생성
EXPLAIN 및 PROFILE 로 SELECT 성능 체크