느린 쿼리는 데이터베이스 성능 저하의 주범이다. 이를 식별하고 분석하는 방법은 아래와 같은 순서로 진행할 수 있다.
-- 슬로우 쿼리 로그 활성화
SET GLOBAL slow_query_log = 1;
-- 슬로우 쿼리 저장 경로 확인
SHOW VARIABLES LIKE 'slow_query_log_file';
-- 특정 시간 이상 걸리는 쿼리만 기록 (예: 1초 이상)
SET GLOBAL long_query_time = 1;
로그는 일반적으로 /var/lib/mysql/ 또는 /var/log/mysql에 생성된다.
cat /var/lib/mysql/slow.log
mysqldumpslow -s t /var/lib/mysql/slow.log
정밀한 분석 도구로, 쿼리 유형별 통계를 제공한다.
pt-query-digest /var/lib/mysql/slow.log
EXPLAIN
SELECT *
FROM user
WHERE email = 'example@naver.com';
| 원인 | 설명 |
|---|---|
| 인덱스 없음 | WHERE 조건, JOIN 조건에 인덱스 없음 |
| LIKE '%검색어%' | 인덱스 무시됨 |
| ORDER BY + LIMIT | 정렬 + 슬라이싱이 느림 |
| 너무 많은 JOIN | 불필요한 조인이나 N:M 조인 |
| 서브쿼리 사용 | 비효율적인 중첩 쿼리 |
| 데이터 양 많음 | 테이블이 커졌는데 최적화 미실시 |
| 함수 인덱스 안 씀 | WHERE DATE(created_at) 같은 인덱스 무효화 |
| 항목 | 설명 |
|---|---|
| 실행 계획 | EXPLAIN 전후 비교 |
| 실행 시간 | SHOW PROFILE, ANALYZE, 또는 ORM log |
| IO 횟수 | 디스크 액세스 횟수 줄이기 |
| 쿼리 캐시 활용 | MySQL에서는 query_cache가 사용 가능 (MySQL 5.x) |
| 결과 개수 | 불필요하게 많은 결과를 가져오지 않도록 LIMIT 등 사용 |
spring.jpa.show-sql=truelogging.level.org.hibernate.SQL=DEBUG| 도구 | 설명 |
|---|---|
| APM (NewRelic, Datadog, Pinpoint) | 느린 요청/쿼리 자동 식별 |
| MySQL Enterprise Monitor | 슬로우 쿼리 탐지 기능 |
| pg_stat_statements (PostgreSQL) | 가장 무거운 쿼리 확인 가능 |
| Grafana + Prometheus | 쿼리 시간 그래프화 가능 |
느린 쿼리를 식별하려면 다음과 같은 단계적인 접근이 중요하다.