APM 툴에서 정기적으로 실행되는 쿼리가 평균 25초 정도 소요되어 성능 개선이 필요했습니다. 이 쿼리는 30분마다 실행되는 배치 작업에 사용됩니다.
문제점
기존 쿼리는 다음과 같은 문제점을 가지고 있었습니다:
- Using filesort와 Using temporary가 실행 계획에 포함됨.
- reg_date 칼럼에 인덱스를 걸어도 정렬 처리에서 인덱스를 사용하지 못함.
예시
SELECT
...(필요한 컬럼들)
FROM
A
INNER JOIN ON
INNER JOIN ON
INNER JOIN ON
INNER JOIN ON
WHERE
조건문 1
AND 조건문 2
ORDER BY
`some_table`.`reg_date` ASC;
주요 원인
- Using filesort: ORDER BY 처리가 인덱스를 사용하지 못할 때 발생하며, 조회된 레코드를 정렬용 메모리 버퍼에 복사해 정렬합니다.
- Using temporary: 임시 테이블을 사용하여 결과를 정렬합니다.
해결 방안
- created_at에 인덱스를 추가해 ORDER BY 절에서 인덱스를 사용할 수 있도록 처리:
- 그러나 WHERE 절에서 created_at을 사용하지 않기 때문에 인덱스가 정상적으로 작동하지 않음.
- 비즈니스 로직상 WHERE 절에 created_at을 추가할 수 없으므로 이 방법은 사용 불가.
- ORDER BY 구문을 삭제하고 애플리케이션 로직에서 정렬 처리:
- 비즈니스 로직상 ORDER BY를 통한 정렬이 중요하지 않기에 애플리케이션 로직을 변경해서 처리함.
최적화 후 쿼리 실행 시간
- AS-IS: 약 29초 소요
- TO-BE: 약 19초 소요 (약 10초 감소)
최적화된 쿼리 예시
최적화된 쿼리는 ORDER BY 구문을 제거하고, 애플리케이션에서 정렬을 처리하도록 변경했습니다.
SELECT
...(필요한 컬럼들)
FROM
A
INNER JOIN ON
INNER JOIN ON
INNER JOIN ON
INNER JOIN ON
WHERE
조건문 1
AND 조건문 2;
이 쿼리는 데이터베이스에서 직접 정렬을 처리하지 않고, 애플리케이션에서 정렬을 수행하도록 하여 성능을 개선했습니다.
결론
ORDER BY 구문 한줄을 삭제함으로써, 쿼리 실행시간을 약 10초 정도 줄일 수 있었습니다. 이 과정에서 해당 쿼리에 대한 실행계획을 이해하고 튜닝을 진행하는것 뿐만아니라 해당 쿼리의 각 부분이 실제로 유용하게 쓰이고 있는지 불필요한 정렬이 발생하고 있는건 아닌지와 같은 부분을 토대로 튜닝을 진행할 수 있었습니다.