01.인덱스 구조

(1) 범위스캔

범위스캔(Range Scan)

  • 인덱스는 키 컬럼 순으로 정렬되어 특정 위치에서 스캔을 시작해 검색조건에 일치하지 않는 값을 만나는 순간 멈춤
  • IOT 를 제외하면 일반적인 힙구조 테이블에서 불가능함
    cf.힙구조:데이터 저장시 랜덤 저장
  • 정렬상태가 유지되도록 데이터를 입력해되 옵티마이저가 신뢰해서 Table Range Scan 실행계획을 세우지 않음.

(2) 인덱스 기본 구조

B\*tree 인덱스

  • 루트(Root) 를 포함한 브랜치(Branch) 블록에 저장된 엔트리에 하위 노트 블룩 찾아가기 위한 DBA(Data Block Address)를 갖고,
  • 최말단 리프(Leaf) 블럭에는 인덱스 키 컬럼과 rowid 를 갖으며, rowid 순으로 정렬됨
  • 브랜치 노드 : 각 엔트리 키값과 하위노드의 블럭주소
  • Imc(LeftMost Child) : 키 값을 갖지 않는 엔트리로 각 브랜치 노드의 첫번째 엔트리
    명시적인 키 값을 갖지 않더라도 "키 값을 가진 첫번째 엔트리보다 작은 값"의 의미
    브랜치 블록의 자식 노드 중 왼쪽 끝에 위치한 블럭
  • 인덱스와 테이블 레코드는 인덱스 구성컬럼이 모두 null 인 레코드를 제외하면 1:1 대응관계 (클러스터 인덱스 1:M )
  • 브랜치에 저장된 레코드 개수는 바로 하위 레벨블록 개수와 일치
  • 인덱스 리프노드상 레코드와 테이블 레코드는 값도 서로 일치 : 테이블값이 갱신되면 리프노드 인덱스 키 값도 같이 갱신
    cf. 리프노드상 엔트리 키 값이 갱신되더라도 브랜치 노드 까진 바뀌진 않음.
    브랜치 블록에 놓인 엔트리는 자신의 키 값과 같거나 큰 값을 담는 하위 노트 블록을 포인팅하는 것으로, 그 키 값은 자식 노트가 갖는 값의 범위를 나타내기 때문에 키 값과 하위 노드의 첫번째 레코드와 정확히 일치하지 않음.
  • 브랜치 노드는 인덱스 분할에 의해 새로운 블록이 추가되거나 삭제(다른 브랜치 자식 노드로 이동) 될때만 갱신

(3) 인덱스 탐색

수직적 탐색 : 범위스캔(Range Scan) , 수평적 탐색을 위한 시작점을 찾는 과정
수평적 탐색 : 리프블록을 인덱스 레코드간 논리적 순서 에 따라 좌,우 스캔

브랜치 블록 스캔

결합 인덱스 구조와 탐색

(ex) deptno + sal 결합인덱스 : deptno = 20 and sal >= 2000 조건으로 쿼리

(4) ROWID 포맷

  • rowid 는 데이터 파일 번호, 블록 번호, 로우 번호 같은 테이블 레코드의 물리적 위치정보를 포함
  • 테이블 레코드를 찾아가는데 필요한 주소 정보이므로 인덱스에 저장, 조회는 가능하나 테이블에 실제 저장돼 있지 않음. pseudo 컬럼
  • 인덱스 없이 rowid 조회 : 오브젝트 및 데이터파일 번호, 파일내에서의 상대적인 블록번호가 데이터 블록 헤더에 저장돼 있음
    읽는 시점에 현재 도달한 블록 해더와 각 레코드에 할당된 슬롯번호로 가공
  • 저장공간 : 7버전 이전 : 6바이트 (파일번호, 블록번호, 로우번호 로 구성)
    8버전 이후 : 10바이트 (데이타량 증가, 파티션 같은 기능 지원위해 오브젝트 번호까지 저장, peta-byte 단위 데이터 저장)
  • 데이블과 인덱스 유형에 따라 6바이트 공간차지 하는 경우
    1) 파티션되지 않은 일반 테이블에서 생성된 인덱스
    2) 파티션된 테이블에 생성한 로컬 파티션 인덱스
  • 10바이트 차지
    1) 파티션 테이블에 생성한 글로벌 파티션 인덱스
    2) 파티션 테이블에 생성한 비파티션 인덱스
  • 제한 rowid 포맷 (오라클 7버전 이전) : 구분자 .(dot) 기호 포함 18자리 문자열
    1) 데이터파일 번호 (4자리) : 로우가 속한 데이타파일번호, 데이타베이스 내 유일값
    2) 블록번호(8자리) : 데이타파일 내에 상대적인 번호
    3) 로우번호(4자리) : 블록내에서 각 로우의 일련번호, 0부터 시작

  • 확장 rowid 포멧 : 연속된 18자리 문자열
    1) 데이터 오브젝트 번호(6자리) : 세그먼트 식별을 위해 사용
    2) 데이터파일 번호 (3자리) : 테이블 스페이스 내에서의 상대적 파일 번호
    3) 블록번호(6자리) : 데이타파일 내에 상대적인 번호
    4) 로우번호(3자리)
 
SELECT 
  rowid 
FROM url_trace a 
--------------------------------------------
AAA6Y2AARAAAAkTAAA
AAA6Y2AARAAAAkTAAB
AAA6Y2AARAAAAkTAAC
AAA6Y2AARAAAAkTAAD
AAA6Y2AARAAAAkTAAE
AAA6Y2AARAAAAkTAAF
AAA6Y2AARAAAAkTAAG
AAA6Y2AARAAAAkTAAH
AAA6Y2AARAAAAkTAAI
AAA6Y2AARAAAAkTAAJ 

-rowid 디코딩


select rowid extended_format 
, dbms_rowid.rowid_to_restricted(rowid,0) restricted_format
, dbms_rowid.rowid_object(rowid) object
, dbms_rowid.rowid_relative_fno(rowid) file_o
, dbms_rowid.rowid_block_number(rowid) block_no
, dbms_rowid.rowid_row_number(rowid) row_number
, rowid 
FROM url_trace 
--------------------------------------------
AAA6Y2AARAAAAkTAAA	00000913.0000.0011	239158	17	2323	0	AAA6Y2AARAAAAkTAAA
AAA6Y2AARAAAAkTAAB	00000913.0001.0011	239158	17	2323	1	AAA6Y2AARAAAAkTAAB
AAA6Y2AARAAAAkTAAC	00000913.0002.0011	239158	17	2323	2	AAA6Y2AARAAAAkTAAC
AAA6Y2AARAAAAkTAAD	00000913.0003.0011	239158	17	2323	3	AAA6Y2AARAAAAkTAAD
AAA6Y2AARAAAAkTAAE	00000913.0004.0011	239158	17	2323	4	AAA6Y2AARAAAAkTAAE
AAA6Y2AARAAAAkTAAF	00000913.0005.0011	239158	17	2323	5	AAA6Y2AARAAAAkTAAF
AAA6Y2AARAAAAkTAAG	00000913.0006.0011	239158	17	2323	6	AAA6Y2AARAAAAkTAAG
AAA6Y2AARAAAAkTAAH	00000913.0007.0011	239158	17	2323	7	AAA6Y2AARAAAAkTAAH
AAA6Y2AARAAAAkTAAI	00000913.0008.0011	239158	17	2323	8	AAA6Y2AARAAAAkTAAI

-rowid 포멧 타입 확인


select 
   dbms_rowid.rowid_type('AAA6Y2AARAAAAkTAAA') 	extended_format 
  , dbms_rowid.rowid_type('00000913.0000.0011') restricted_format  
from dual 
--------------------------------------------
1	0

-데이타 오브젝트 번호, 데이타파일 번호 확인