월별 정산 조회 쿼리에서 조건 하나를 '<'에서 '<='로 바꿨을 뿐인데 쿼리 시간이 급격히 증가한 사례를 정리한다.
원인은 옵티마이저의 인덱스 선택이 바뀌면서 "대량 범위 스캔"이 발생했기 때문이다.
테이블
- T_RECEIPT: 월별 정산 내역(대용량)
- T_CONTRACT: 계약 내역
- T_TARGET: 조회 대상 계약 내역(필터 역할)
쿼리
SELECT A.CONTRACT_NO
, SUM(A.AMOUNT) AS AMOUNT
FROM T_RECEIPT A
JOIN T_CONTRACT B ON A.CONTRACT_NO = B.CONTRACT_NO
WHERE EXISTS (SELECT 1 FROM T_TARGET S WHERE S.CONTRACT_NO = A.CONTRACT_NO)
AND A.SUM_YYMM <= '202512' -- 여기서 '<' → '<=' 변경
GROUP BY A.CONTRACT_NO;
현상
- A.SUM_YYMM < '202512'일 떄는 빠름
- A.SUM_YYMM <= '202512'로 바꾸자 엄청 느려짐
원인(실행계획을 확인해보니 인덱스 선택이 바뀜)
| 인덱스명 | 컬럼 | 특징 |
| INDEX01_RECEIPT | (CONTRACT_NO) | 계약번호 기반 접근에 유리 |
| INDEX02_RECEIPT | (SUM_YYMM, CONTRACT_NO) | 월 기준 범위 조건에 유리 |
인덱스 선두 컬럼이 범위 조건이면 별 차이 없을것 같지만, 오히려 스캔 범위가 넓어질수록 인덱스가 오히려 느려질 수 있다.
옵티마이저가 월 선두 인덱스(SUM_YYMM)를 타면 SUM_YYMM가 '202512'라서 과거부터 당월까지 거의 전 구간이 스캔됨
즉 한 글자 변경 → 스캔 범위 증가 + 계획 변경 → "폭망"이 되었다.
해결
드라이빙을 CNTR_NO로 강제(힌트)해서 INDEX01로 타게 했다.
SELECT /*+ INDEX(A INDEX01_RECEIPT) */
A.CONTRACT_NO
, SUM(A.AMOUNT) AS AMOUNT
FROM T_RECEIPT A
JOIN T_CONTRACT B ON A.CONTRACT_NO = B.CONTRACT_NO
WHERE EXISTS (SELECT 1 FROM T_TARGET S WHERE S.CONTRACT_NO = A.CONTRACT_NO)
AND A.SUM_YYMM <= '202512' -- 여기서 '<' → '<=' 변경
GROUP BY A.CONTRACT_NO;'Database' 카테고리의 다른 글
| myql 메모 (0) | 2025.06.18 |
|---|---|
| MySQL:ALTER TALBE ADD COLUMN이 오래 걸리는 경우 (0) | 2025.05.19 |
| GROUP BY ROLLUP (0) | 2025.04.29 |
| 쿼리 숫자형 텍스트 정렬 (0) | 2023.11.22 |
| JDBC-8038:Expression is not in a GROUP BY clause. (0) | 2023.11.02 |