만약 웹상에서 특정 텍스트박스를 통해 바인드변수 v1을 입력받는다고 해보죠. 그리고 이 v1을 가지고 검색을 합니다. 따라서 이 v1이 해당되는 id 컬럼에 인덱스를 준다고 해보죠.
그런데 이 id컬럼은 100이란 값이 90%이고 나머지 값들이 10%를 차지한다고 하면, 인덱스 스캔시 100이란 값을 인덱스 스캔하면 퍼포먼스가 나쁩니다. 아시다시피 인덱스는 테이블의 10~15%선에서 스캔해야하며 그것도 매우 절대적 갯수로도 적은수의 row여야만 합니다.
왜냐하면 인덱스 스캔은 single block i/o이며 이것은 multi block i/o(DB_MULTIBLOCK_IO_COUNT 에 의해서 결정됨) 에 비해서 훨씬 느리기 때문이죠.
이럴때는 나머지 10%를 위해 인덱스를 생성하게 되는거죠. 그리고 90%의 값이 100에 대해서는 풀 테이블 스캔을 하도록 해야합니다.
쿼리는 다음과 같이 해야합니다.
select * from xxx
where :v1 = 100
and id||'' = :v1
union all
select * from xxx
where :v1 <> 100
and id = :v1
중간에 ||'' 를 사용하여 좌변을 가공함으로써 인덱스 스캔을 막았습니다. 이 방법외에도 힌트(/*+ FULL(xxx) */)를 주어서 풀 테이블 스캔을 유도하는 방법도 있습니다.
보통 문자열은 ||'' 를 해서 인덱스를 죽이고, 숫자는 +0을 합니다. 그러나 힌트가 더 좋은 방법이며 추천되는 방법입니다. 왜냐하면 앞으로 옵티마이저의 성향이 어찌 바뀔지 모르기때문에 가공하는 것만으로는 완벽하지 않기때문이죠.
|