개발/좋은 개발 습관
데이터 비교는 어떻게 해야 할까? – 성능을 살리는 DB 쿼리 작성법
뇽.뇽
2025. 5. 8. 13:22
반응형
반응형
데이터베이스에서 값을 비교할 때, 많은 사람들이 DB에서 꺼낸 값을 가공해서 비교하려는 실수를 자주 합니다. 이는 성능 저하의 원인이 되며, 특히 대용량 데이터가 있는 테이블에서는 심각한 병목을 유발할 수 있습니다.
오늘은 실무에서 자주 마주치는 비교 연산 시 컬럼을 가공하지 말고, 비교할 값을 가공하라는 원칙을 이야기하려 합니다.
잘못된 예시 – 컬럼을 가공하면 인덱스는 무용지물
TO_CHAR(REGDT, 'YYYYMMDD') <![CDATA[ >= ]]> #{searchStaDe}
이 쿼리는 마이바티스에서 REGDT라는 컬럼을 먼저 문자형으로 변환한 후, searchStaDe 값과 비교합니다.
문제는 이때 REGDT 컬럼에 인덱스가 걸려 있어도 사용되지 않는다는 점입니다.
- TO_CHAR(A.REGDT, ...)는 함수로 감싼 형태이기 때문에 옵티마이저는 해당 인덱스를 무시합니다.
- 결국 풀 스캔이 일어납니다.
올바른 예시 – 비교값을 가공하면 인덱스는 그대로 사용된다
REGDT <![CDATA[ >= ]]> TO_TIMESTAMP(#{searchStaDe} || '000000', 'YYYYMMDDHH24MISS')
이 방식은 A.REGDT는 그대로 두고, 비교할 파라미터 값만 TO_TIMESTAMP()로 변환하여 비교합니다.
장점:
- REGDT에 인덱스가 있을 경우 정상적으로 인덱스를 사용합니다.
- 성능이 훨씬 빠릅니다.
- 쿼리 계획(Explain Plan)을 보면 INDEX RANGE SCAN으로 처리되는 것을 확인할 수 있습니다.
실무에서는 이렇게 써야 합니다
대부분의 실무에서는 날짜 조건을 쿼리에서 자주 사용합니다. 이때 다음과 같은 원칙을 기억하세요.
성능 최적화를 위한 쿼리 작성 원칙
- 컬럼에는 함수 사용을 피하라
- 비교할 값(파라미터, 상수)을 가공하라
- 컬럼에 인덱스가 있다면 그것을 활용할 수 있도록 설계하라
보너스: BETWEEN을 쓸 때도 마찬가지!
잘못된 예:
TO_CHAR(REGDT, 'YYYYMMDD') BETWEEN #{staDt} AND #{endDt}
좋은 예:
REGDT BETWEEN TO_TIMESTAMP(#{staDt} || '000000', 'YYYYMMDDHH24MISS')
AND TO_TIMESTAMP(#{endDt} || '235959', 'YYYYMMDDHH24MISS')
정리하며…
데이터를 다룰 때는 단순히 "동작하는 쿼리"보다, "성능까지 고려한 쿼리"가 중요합니다.
특히 실시간 처리가 필요한 시스템이나 배치에서 대량 데이터를 다룰 경우,
함수 사용 하나만으로도 시스템에 부담을 줄 수 있습니다.
다음에 쿼리를 작성할 때는 꼭 기억하세요:
비교할 값을 가공해라. 컬럼은 그대로 놔둬라
반응형