Contents

범위 스캔

  • 인덱스는 대용량 테이블에서 필요한 데이터만 빠르고 효율적으로 액세스할 목적으로 사용하는 오브젝트다..
  • 인덱스는 키 컬럼 순으로 정렬돼 있기 때문에 특정 위치에서 스캔을 시작해 검색 조건에 일치하지 않는 값을 만나는 순간 멈출수있다.

인덱스 기본 구조

  • 인덱스 기본 구조
    \*\* Root, Branch 블록에 저장된 엔트리에는 하위 노드 블록을 찾아가기 위한 DBA 정보를 갖고 있다.
    • Leaf 블록에는 인덱스 키 컬럼과 함계 해당 테이블 레코드를 찾아가기 위한 주소정보(rowid)를 갖는다.
    • Leaf 블록은 항상 키 컬럼 순으로 정렬돼어 있기 때문에 범위스캔이 가능하다.
    • 키 값이 같을때는 rowid 순으로 정렬된다.
      • LeafMostChild
        키 값을 갖지 않는 특별한 엔트리(lmc)
        lmc는 명시적인 키 값을 갖지 않더라도 '키 값을 가진 첫 번째 엔트리보다 작은 값의 의미
        브랜치 블록의 자식 노드 중 가장 왼쪽 끝에 위치한 블록을 가리킴
    • 오라클은 인덱스 구성 컬럼이 모두 null 인 레코드는 저장하지 않는다.
    • Branch 에 저장된 레코드 개수는 바로 하위 레벨 블록 개수와 일치한다.
    • 테이블 레코드에서 값이 갱신되면 리프 노드 인덱스 키 값도 같이 갱신된다.
    • Leaf Node 상의 엔트리 값이 갱신되더라도 Branch Node 까지 값이 바뀌지는 않는다.

인덱스 탐색

  • 인덱스 탐색은 수직적 탐색과 수평적 탐색으로 구분해 설명할 수 있다.
    • 수평적 탐색은 범위스캔 을 말하는 것이며 리프 블록을 인덱스 레코드 간 놀리적 순서에 따라 스캔하기 때문에 수평적 이라고 표현한다.
    • 수직적 탐색은 수평적 탐색을 위한 시작 지접을 찾는 과정으로 루트에서 리프 블록까지 아래쪽으로 진행한다.
  • Branch 블록 스캔
    \*\* Branch 블록을 스캔할 때는 뒤에서부터 스캔하는 방식이 유리하다.
    • 실제적으로 뒤쪽부터 스캔하는지는 알수없다. (가정)
    • Branch 블록을 따라 수직적 탐색을 진행할 때는 찾고자 하는 값보다 키 값이 작은 엔트리를 따라 내려간다.
  • 결합 인덱스 구조와 탐색
    \*\* 'deptno = 20 and sal >= 2000' 으로 쿼리시 두번째 리프 두번째 레코드부터 탐색.
    • 수직적 탐색 과정에서 deptno 와 sal 을 같이 필터링 하기 때문.

ROWID 포맷

  • ROWID 에는 데이터 파일 번호, 블록 번호, 로우 번호 같은 테이블 레코드의 물리적 위치정보를 포함한다.
  • 인덱스를 거치지 않는 쿼리에서는 파일 내에서의 상대적인 블록 번호가 데이터 블록 헤더에 저장되어 있다.
  • 인덱스에 저장되는 ROWID는 oracle 7 버전 까지는 6byte 이후에는 10byte로 증가되었다. (경우에 따라 다르다)
    • 6byte 를 사용하는 경우
      파티션 되지 않은 일반 테이블에 생성한 인덱스
      파티션된 테이블에 생성한 로컬 파티션 인덱스
    • 10byte 를 사용하는 경우
      파티션 테이블에 생성한 글로벌 파티션 인덱스
      파티션 테이블에 생성한 비파티션 인덱스
  • 6 byte 인덱스 포맷 (블록)(로우)(데이터파일)
    • 데이터파일 번호 (4자리)
    • 블록 번호 (8자리)
    • 로우 번호 (4자리)
  • 10 byte 인덱스 포맷 (데이터 오브젝트)(데이터파일)(블록)(로우)
    • 데이터 오브젝트 번호(6자리)
    • 데이터파일 번호(3자리)
    • 블록번호(6자리)
    • 로우번호 (3자리)
  • dbms_rowid pkg

SQL> select rowid extended_format
  2       , dbms_rowid.rowid_to_restricted(rowid, 0) restricted_format
  3       , dbms_rowid.rowid_object(rowid) object
  4       , dbms_rowid.rowid_relative_fno(rowid) file_no
  5       , dbms_rowid.rowid_block_number(rowid) block_no
  6       , dbms_rowid.rowid_row_number(rowid) row_number
  7  from   emp e
  8  where  empno = 7369;

EXTENDED_FORMAT    RESTRICTED_FORMAT      OBJECT    FILE_NO   BLOCK_NO ROW_NUMBER
------------------ ------------------ ---------- ---------- ---------- ----------
AAASwgAABAAAVyRAAA 00015C91.0000.0001      76832          1      89233          0

  • rowid_type

SQL> select dbms_rowid.rowid_type('AAASwgAABAAAVyRAAA') extended_format
  2       , dbms_rowid.rowid_type('00015C91.0000.0001') restricted_format
  3  from   dual;

EXTENDED_FORMAT RESTRICTED_FORMAT
--------------- -----------------
              1                 0

  • 데이터 오브젝트 번호 와 데이터 파일 번호를 이용한 정보 조회

SQL> select object_id, owner, object_name, subobject_name
  2  from   dba_objects
  3  where  data_object_id = 76832;

 OBJECT_ID OWNER                          OBJECT_NAME                                                                                 SUBOBJECT_NAME
---------- ------------------------------ -------------------------------------------------------------------------------------------------------------------------------- ------------------------------
     76832 SYS                            EMP

SQL> select file_id, file_name, tablespace_name
  2  from   dba_data_files
  3  where  relative_fno = 1;

   FILE_ID
----------
FILE_NAME
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TABLESPACE_NAME
------------------------------
         1
/oracle/oradata/INDEX/system01.dbf
SYSTEM

\*