by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

1. 인덱스 구조




01 인덱스 구조

(1) 범위스캔

인덱스는 키 컬럼 순으로 정렬돼 있기 때문에 특정 위치에서 스캔을 시작해 검색 조건에 일치하지 않는 값을 만나는 순간 멈출 수 있음
(IOT 를 제외한 일반 힙구조테이블에서 범위스캔은 없음)

(2) 인덱스 기본 구조

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 관계이기 때문에...)
반면, 리프노드상의 엔트리 카값이 갱신되더라도 브랜치노드까지 항상 바뀌지는 않는다.
(브랜치블록에 놓인 엔트리는 자식노드가 갖는 값의 범위를 나타내기 때문)
브랜치노드는 인덱스 분할에 의해 새로운 블록이 추가되거나 삭제될 때만 갱신된다.

(3) 인덱스 탐색

수평적 탐색: 범위스캔
수직적 탐색: 수평적 탐색을 찾기 위한 시작지점을 찾는 과정.루트에서 리프블록까지 아래쪽으로 진행.

<그림 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번 과정을 반복하다가 검색조건을 만족하지 못하는 레코드를 만나는 순간 멈춘다,

(4) ROWID 포맷

  • 테이블 레코드의 물리적 위치정보를 포함.(데이터파일번호, 블록번호, 로우번호 등)
  • 테이블에 저장되는 것이 아니라 인덱스에 저장됨.
  • pseudo컬럼.
  • 오라클 7버전까지 6바이트.(파일번호, 블록번호, 로우번호)
  • 오라클 8버전이후
    ( 10바이트 : 파티션 테이블에 생성한 글로벌 파티션 인덱스, 파티션 테이블에 생성한 비파티션 인덱스)
    ( 6바이트 : 파티션되지 않은 일반 테이블에 생성한 인덱스, 파티션된 테이블에 생성한 로컬 파티션 인덱스)

<제한rowid포맷>

  • 오라클7버전까지 사용
  • 3개의 구성요소로 이루어짐.
    데이터파일 번호(4자리) : 로우가 속한 데이터파일 번호, 데이터베이스내에서 유일 값.
    블록번호(8자리) : 로우가 저장된 데이터 블록 번호, 데이터파일 내에서의 상대적 번호
    로우번호(4자리) : 블록 내에서 각 로우에 붙여진 일련번호, 0부터 시작
  • 구분자로 사용하는 '.(dot)' 기호를 포함해 18자리 문자열.
  • 순서는 블록, 로우, 데이터 파일 순.
    (00000DD5.0000.0001)

<확장rowid포맷>

  • 오라클8버전부터 사용
  • 4개의 구성요소로 이루어짐.
    데이터 오브젝트 번호(6자리) : 세그먼트를 식별하기 위해 사용되는 데이터 오브젝트 번호
    데이터파일 번호(3자리) : 로우가 속한 데이터파일 번호 (테이블스페이스 내에서의 상대적인 파일 번호)
    블록번호(6자리) : 로우가 저장된 데이터 블록 번호, 데이터파일 내에서의 상대적 번호
    로우번호(3자리) : 블록 내에서 각 로우에 붙여진 일련번호, 0부터 시작
  • 순서: (데이터오브젝트)(데이터파일)(블록)(로우)
  • 포맷은 별도 구분 없이 연속된 18자리 문자열
  • rowid를 자릿수만큼 잘라서 디코딩(Decoding)하면 각 구성요소에 대한 정보 출력 (혹은 dbms_rowid패키지 사용)

본 문서는 조시형저, 오라클 성능고도화 원리와 해법2 를 참고하였습니다.

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.