함수와 인덱스 사용

Rupert Harwood -

방금 전 개발자와 다음과 같은 문제에 직면하여 블로깅을 할 필요가 있다고 생각했습니다.
저희 제품의 모니터링 UI에서 다음과 같은 쿼리를 실행하고 있었습니다:

 

 어느 순간, 우리는 조건절에 timestamp = ‘2013-12-12 12:01’를 사용했었으나 이상한 timezone 이슈를 피하기 위해, UI 코드 전체에서 integer UNIX timestamp를 사용하도록 unix_timestamp(timestamp) = 1389210952와 같이 변환했습니다.

그러나, 이로 인해 쿼리는 5초가 걸릴 만큼 성능이 매우 좋지 못했습니다. 다음 실행계획이 그 이유를 설명해줍니다.

index_scan 행에서 table.representation 이후에 아무 것도 나타나지 않는다는 것은 SARG(index를 사용하여 검색)를 하지 못하고 있다는 것을 의미하므로 전체 테이블을 읽고 나서 해당 timestamp와 일치하는 결과를 필터링하고 있는 것입니다.

해당 컬럼에 함수를 사용할 때에는 컬럼에 대한 인덱스를 사용할 수 없는 것이 문제입니다(참고로, MySQL에서도 동일한 문제 발생).  그러나, 이 문제는 다음과 같이 함수 호출을 표현식의 반대편으로 이동함으로써 쉽게 제거할 수 있습니다.  timestamp = from_unixtime(123234235).


다음과 같이 실행 계획은 이제 SARG (index_scan 행에서 콤마 바로 다음)를 통해 소수의 행만 읽음으로써 실행 시간이 매우 짧다는 것에 주목해주십시오.


함수 호출을 상수 쪽으로 옮김으로써 인덱스를 사용할 수 있는 반면, 상수 반대에서의 함수 호출은 플래너가 인덱스에서 값 분포에 대한 통계값을 활용하는 기능을 방해한다는 점, 다시 말해 인덱스를 사용하여 적절한 플랜에 대한 비용을 산출하지 못한다는 점에 주목할 필요가 있습니다. 따라서, 상수 파라미터에 함수 호출을 사용할 때 단순 상수를 제공했다라고 한다면 플래너는 다른 플랜을 선택할 것입니다(예를 들어, 데이터베이스가 아닌 애플리케이션에서 해당 함수를 수행했을 때).  그러므로, 애플리케이션내에서 상수에 함수를 적용하는 것이 때로는 가장 좋지만, 만약 이것이 여의치 않거나 바람직 하지 않은 경우 (데이터베이스에서 시간대 변환을 처리하기 위해 이를 데이터베이스에 남겨두는 경우), 인덱스 선택 (FORCE 또는 USE INDEX (index_name))을 강제하도록 플래너 힌트를 사용할 수도 있습니다.

해당 아티클은 최초 Nathan Parrish에 의해 작성되었습니다.

또 다른 질문이 있으십니까? 문의 등록

0 댓글

댓글을 남기려면 로그인하세요.
Zendesk 제공