본문 바로가기

ORACLE

index의 바인딩 변수 조건에 따른 선택

 

A 업체에서 운영하는 교육센터가 있다고 할때


아무래도 이 교육센터에서 교육을 받는 사람들은 대부분 그 A업체의 사람들일 것이다.


분포도가 만약 A업체 교육자가 90%, 나머지 타 업체가 10%라고 하면


검색을 할때 조건에 A업체 소속인 사람들... 이라고 나오면 fullscan이 유리하고 (분포도가 나쁘므로)


타 업체 소속인 사람들.... 이라고 한다면 index scan이 빠를 것이다. (분포도가 좋으므로..)


관리자의 화면에서 업체id를 입력받아 출력을 하는 부분이 있다고 할때 만약 sql을


(입력 받은 업체id는 바인딩변수 v1에 넣는다)


(corp_id로 인덱스가 만들어져있음)

select * from XXX where corp_id = :v1 단순하게 이렇게 만든다면..


A업체 id가 입력되었을 경우에는 느린 수행 속도를..


타업체 id가 들어왔을 경우에는 무지하게 빠른 수행 속도가 나온다.


중요한점은 A업체 id가 들어왔을땐 full scan을


아닐땐 index를 사용하게 하는 것이 중요하다.


그렇다면 sql을 이렇게 바꾸어보자..


(A업체의 id는 100)


select * from XXX

where :v1 = '100'

and corp_id||'' = :v1

union all

select * from XXX

where :v1 <> '100'

and corp_id = :v1


중요한 것은 두 sql중 하나가 참이면 하나가 거짓으로 만들어 버리는 것이다. (공집합으로..

sql은 집합이다.)


그리고 위 빨강 부분은 A업체 id가 들어왔을때 index를 사용하지 못 하도록

||''를 사용 다리를 분지른 것이다.. 기억하자. 좌변이 가공되면 인덱스를 사용하지 못 한다.


substr(XXX)='100' , length(XXX) = '120' 등등..




추가적으로 입력받는 필드가 업체id와 수강생id 두 가지가 있다고 할때


select * from XXX

where corp_id like :v1||'%'

and std_id like :v2||'%'


이런식으로 만들면...... 어차피 sql이 실행될때 index는 두개의 컬럼 중 하나만 타게 될 것이고

corp_id를 만약 입력하지 않고 조회를 할 경우

corp_id like :v1||'%'는 무조건 full scan이 되기 때문에...

(corp_id like '%'...무조건 참이니까..)


fullscan + std_id를 조회하기 위해 각 fullscan에 대한 table acess가 되기 때문에


수행속도가 장난이 아니다..--;