본문 바로가기

ORACLE

Index Merge 방식의 실행계획

 

주문내역이라는 chol이라는 테이블이 있을때

인덱스는 고객넘버인 custno+ 처리상태값인 status로 잡혀있다고 하면


select * from chol where custno='30' and status='90';


을 실행할때 인덱스 merge방식을 사용하게 된다. 두개의 조건에 대해 모두 인덱스가 잡혀있고

조건이 '='로서 처리 우선 순위가 동일하기 때문이다.


인덱스는 같은 값을때는 rowid순으로 sort가 되어있다.


예를 들어

idx_custno                                  idx_status

10      row1                                 30  row2

10      row30                               30 row3

10      row31                                30 row10

10      row40                                90 row20

30      row 54                               90 row30

30      row 55                               90 row54

30      row 60                               90 row57

30     row 61                                 90 row 61

30     row 62


이런식으로 같은 값에 대해서는 rowid순으로 정렬이 되어있는 것이다.

따라서 위의 경우 인덱스를 타게 되면 idx_custno일경우 값이 30인 경우부터(rowid 54)

idx_status는 값이 90인경우부터 (rowid 20) 인덱스를 타게 되고..

두개의 rowid가 같은 경우가 바로 위 쿼리에서 두 조건을 모두 만족하게 되는 경우인 것이다.


따라서 최초 custno와 status가 30 과 90인 경우를 비교하여 rowid를 비교.

status의 rowid가 20으로 더 작으므로 그 다음 rowid와 비교(rowid30) 역시 작으므로

그 다음 rowid(54)와 비교. rowid가 일치하므로 이때 테이블을 access하여 원하는 값을

뽑아내고 다시 그 다음 값들은 rowid55와 rowid57을 비교하여  custno쪽이 rowid가 작으므로

다음 rowid...


이런식으로 index를 비교해 나가는 것이다.


그리고 참고로 sql을 데이터베이스가 parsing할때는 뒤에서 부터 하기 때문에 위의 쿼리처럼 같은

상황이라면 idx_status를 먼저 scan하게 된다.


위의 처럼해도 결과는 상당히 빠른 속도로 나오지만 더 빠르게 나오도록 하는 방법이 있다.


가만히 생각해보면 주문처리의 상태값이 90 (예를 들어 배송완료)인 것과 custno가 30인 경우

데이터의 수를 비교해 봤을때 custno가 30인 경우가 훨씩 적을 것이라는 것을 알 수 있다.


어떻게 보면 status로 인덱스를 만들어 놓은 것은 배송완료 된것을 찾는다기 보다는

반품인것, 배송중인것 등을 찾기 위해 만들어 놓은 것이다.


이럴 경우에는 custno의 인덱스만을 사용하는게 좀 더 빠른 속도를 보장한다.

(range가 적으므로)


따라서 위의 쿼리를

select * from chol

where custno='30'

and rtirm(status)='90';


이런식으로 좌변을 인위적으로 가공하여 index를 사용하지 못 하도록 만들면

idx_cust 인덱스만을 사용하며 더 빠른 속도로 결과를 얻어낼 수 있다.