개발/좋은 개발 습관

데이터 비교는 어떻게 해야 할까? – 성능을 살리는 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으로 처리되는 것을 확인할 수 있습니다.

 

 

실무에서는 이렇게 써야 합니다

 

대부분의 실무에서는 날짜 조건을 쿼리에서 자주 사용합니다. 이때 다음과 같은 원칙을 기억하세요.

성능 최적화를 위한 쿼리 작성 원칙

  1. 컬럼에는 함수 사용을 피하라
  2. 비교할 값(파라미터, 상수)을 가공하라
  3. 컬럼에 인덱스가 있다면 그것을 활용할 수 있도록 설계하라

 

 

보너스:   BETWEEN을 쓸 때도 마찬가지!

 

잘못된 예:

TO_CHAR(REGDT, 'YYYYMMDD') BETWEEN #{staDt} AND #{endDt}

 

좋은 예:

REGDT BETWEEN TO_TIMESTAMP(#{staDt} || '000000', 'YYYYMMDDHH24MISS')
           AND TO_TIMESTAMP(#{endDt} || '235959', 'YYYYMMDDHH24MISS')

 


 

정리하며…

 

데이터를 다룰 때는 단순히 "동작하는 쿼리"보다, "성능까지 고려한 쿼리"가 중요합니다.
특히 실시간 처리가 필요한 시스템이나 배치에서 대량 데이터를 다룰 경우,
함수 사용 하나만으로도 시스템에 부담을 줄 수 있습니다.

다음에 쿼리를 작성할 때는 꼭 기억하세요:

 

비교할 값을 가공해라. 컬럼은 그대로 놔둬라

 

반응형