주문내역이라는 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 인덱스만을 사용하며 더 빠른 속도로 결과를 얻어낼 수 있다.