인덱스는 키 컬럼 순으로 정렬돼 있기 때문에 특정 위치에서 스캔을 시작해 검색 조건에 일치하지 않는 값을 만나는 순간 멈출 수 있음
(IOT 를 제외한 일반 힙구조테이블에서 범위스캔은 없음)
P17 그림 1-1 참조
루트(Root)를 포함한 브랜치(Branch)블록에 저장된 엔트리에는 하위 노드 블록을 찾아가기 위한 DBA(Data Block Address) 정보를 갖고,
최말단 리프블록에는 인덱스 키 컬럼과 함께 해당 테이블 레코드를 찾아가기 위한 주소정보(rowid)를 갖는다.
리프블록은 항상 키 컬럼순으로 정렬되어 있기 때문에 범위스캔이 가능하다.
키값이 동일할 때에는 rowid순으로 정렬된다.
LeftMost Child
각 브랜치의 첫번째 엔트리는 키값을 갖지 않는 특별한 엔트리가 있는데 이를 LMC( LeftMost Child )라 한다.
다른 엔트리는 자신의 키값과 같거나 큰 값을 담은 자식 노드블록을 가리키는 반면 LMC는 키값을 가진 첫번째 엔트리 보다 작은 값의 의미를 갖는다.
따라서, 그 브랜치 블록의 자식노드 중 가장 왼쪽 끝에 위치한 블록을 가리킨다.
인덱스와 테이블레코드 간에는 1:1 대응 관계를 갖는다. (클러스터 인덱스는 1:M관계)
오라클은 인덱스 구성컬럼이 모두 null인 레코드는 저장하지 않는다.
브랜치에 저장된 레코드 갯수는 바로 하위 레벨 블록 갯수와 일치한다.
( 그림 1-1에서 루트블록의 레코드가 2개 이므로 브랜치 블록도 2개이다. 브랜치 블록에 놓은 레코드 갯수가 총 8개 이므로 리프블록의 갯수도 8개로 예상된다.)
테이블레코드에서 값이 갱신되면 리프노드 인덱스 키값도 같이 갱신된다.(1:1 관계이기 때문에...)
반면, 리프노드상의 엔트리 카값이 갱신되더라도 브랜치노드까지 항상 바뀌지는 않는다.
(브랜치블록에 놓인 엔트리는 자식노드가 갖는 값의 범위를 나타내기 때문)
브랜치노드는 인덱스 분할에 의해 새로운 블록이 추가되거나 삭제될 때만 갱신된다.
수평적 탐색: 범위스캔
수직적 탐색: 수평적 탐색을 찾기 위한 시작지점을 찾는 과정.루트에서 리프블록까지 아래쪽으로 진행.
<그림 1-1 에서 'CLARK'을 찾는 과정>
1. 루트 블록 스캔
lmc는 KI보다 작은 값을 의미하고, KI는 KI보다 같거나 큰 값을 의미하기 때문에 왼쪽브랜치 블록으로 이동
2. 찾아간 브랜치블록을 스캔하면서 그 다음 찾아갈 인덱스 블록을 탐색한다.
'CLARK'이 'BER' 보다 크고 'FO'보다 작으므로 두번째 레코드가 가리키는 블록주소(18000A7)로 찾아간다.
3.도착한 리프블록에서 'CLARK'을 찾으면 수평적 탐색과정을 하고, 못찾으면 인덱스 탐색을 마친다.
('CLARK'을 찾았으므로 수평적탐색을 진행한다.)
4. 인덱스리프블록을 스캔하면서 값이 'CLARK'인지 확인한다.
5. rowid(00000B1C.001E004)를 이용해 해당 레코드를 찾아간다.
6. 4,5번 과정을 반복하다가 검색조건을 만족하지 못하는 레코드를 만나는 순간 멈춘다,
<제한rowid포맷>
<확장rowid포맷>
본 문서는 조시형저, 오라클 성능고도화 원리와 해법2 를 참고하였습니다.