사용자 도구

사이트 도구


study:oracle:datadb:1week_2

문서의 이전 판입니다!


* B-tree 인덱스 설명은 http://wiki.oracleclub.com/pages/viewpage.action?pageId=1507450 에서 사진 및 내용을 인용하였습니다.^^

제2장 인덱스의 유형과 특징

  • 인덱스란 말 그대로 전체 내용물 중에서 특정한 부분을 바로 찾을 수 있는 목차(目次)나 색인(索引)의 개념.
  • 테이블에 저장되어있는 데이터를 좀 더 효율적이고 빠르게 찾기 위해 사용.
  • 관계형 데이터베이스에서 적용하고 있는 인덱스 유형은 아래와 같음.
    • B-Tree 인덱스
    • 비트맵(Bitmap) 인덱스
    • B-tree 클러스트 인덱스
    • 해쉬(hash)클러스터 인덱스
    • 리버스 키(Reverse key) 인덱스
    • 비트맵 조인(Bitmap join) 인덱스
    • 함수기반(Function-based) 인덱스

2.1 B-tree 인덱스

  • 생성 명령어 : CREATE INDEX 인덱스명 ON 테이블명(컬럼명)
  • 나무구조(Tree)처럼 가지에 해당하는 브랜치 블럭과 잎사귀에 해당하는 리프 블럭이 있다.

2.1.1 B-tree 인덱스의 구조

:——————————————————————————————————

  • Unique Scan일 경우

  • range Scan일 경우
    1. 인덱스는 구성컬럼과 ROWID로 정렬되어 있다.
    2. ROWID에는 로우가 저장된 블록의 주소, 로우의 슬롯번호가 기록되어 있다.
    3. 처리할 범위의 첫번째 인덱스로우를 브랜체블록을 통해 리프블록을 액세스한 다음 거기의 ROWID로 블록을 찾는다.
    4. SGA부터 찾아보고 없으면 디스크에 액세스해서 복사본을 SGA에 복사한다.
    5. 새롭게 액세스한 데이터블록정보를 PGA로 가져와서 해당 SQL의 처리버퍼에 넣는다 (일명 원 버퍼).
    6. 인덱스블록을 액세스한 내용을 PGA버퍼에서 찾아 다른 조건까지 검증하여 성공한 로우만 운반단위로 보낸다 만약 클러스터링 팩터가 좋다면 여러건의 인덱스 스캔을 하나의 버퍼에서 처리할 수 있다.
    7. PGA버퍼에서 찾을 수 없다면 다시 다른 블록을 SGA에 액세스하여 새로운 블럭을 담고 위의 처리를 반복수행한다.
    8. 리프블록에서 액세스한 로우가 처리범위를 넘으면 처리를 종료한다.
  • ROWID의 구성
  • rowid라는 가상 컬럼에 저장된다.
  • Single row access를 위한 row 고유한 주소
  • 10자리로 구성

:——————————————————————————————————

2.1.2 B-tree 인덱스의 조작(Operation)

  • 인덱스 생성(Creation)

  1. 테이블을 액새스하여 정렬을 수행.
  2. 정렬된 결과를 인덱스 세그먼트의 리프 블록에 기록하기 시작.
  3. 리프블록이 PCTFREE에 도달하여 새로운 블록을 요구하게 되면 브랜치블록을 생성.
  4. 리프블록이 증가함에 따라 브랜치블록도 채워져 가다 블랜치블록이 PCTFREE에 도달하면 새로운 리프블록과 새로운 브랜치블록을 생성할때 루트블록이 생성된다.
  5. 새로운 브랜치블록이 만들어질 때마다 루트블록에 브랜치블록의 DBA정보를 기록한다.
  • 위와 같은 방법으로 인덱스가 저장되기 때문에 인덱스 블럭에 많은 로우를 담게 될 경우 리프 블럭 감소, 브랜치 블럭 증가 둔화(블럭의 깊이 감소)
    • 최대한 인덱스 컬럼의 수를 줄인다.
    • 큰 블럭 사이즈(DB_BLOCK_SIZE)를 지정.
    • PCTFREE를 최소로 정의.
    • 압축을 활용하는 방법
CREATE INDEX ord_customer_idx
ON orders (customer_id, sales_id)
COMPRESS 1;

:——————————————————————————————————

  • 인덱스 블럭의 분할(SPILT)
    • 인덱스 로우는 정렬이 되어 저장 되어야 하는 이유 때문에 이미 생성된 구조에 새로운 로우가 삽입되면 기존의 위치에 파고 들어가는 문제 발생

  • 마지막 값이 삽입되는 경우 : 그림처럼 PCTFREE에 도달한 블럭일 경우엔 새로운 블럭에 등록된다.
  • 중간 값이 삽입되는 경우 : PCTFREE가 초과하게 되므로 분할이 발생하는데 어차피 2개의 블럭으로 수정되므로 2/3만 채우도록 하면서 양쪽을 모두 재편하게 됨(또 다른 중간 값이 들어와 계속 분할 되는 것을 방지하기 위함).
  • 하지만 분할이 일어난 블럭에 새로운 값이 들어오지 않으면 저장공간 낭비를 초래하게 되고 이를 해결하기 위해선 인덱스를 재생성하는 방법뿐이다.

:——————————————————————————————————

  • 데이터의 삭제 및 갱신
    • 데이터를 삭제했을 경우 테이블의 로우는 제거되지만 인덱스의 로우는 삭제되었다는 표시(flag)만 추가된다.(저장공간낭비와 스캔시 액세스 블럭 증가)
    • 한 리프 블럭이 모두 삭제 되었을 경우 브랜치 블럭에 해당 리프 블럭을 가리키는 로우도 삭제 표시가 된다.
    • 갱신할 경우 삭제와 삽입이 발생.
    • 이러한 이유로 수정이 빈번하지 않는 컬럼을 인덱스로 사용권장.
    • 데이터처리(DML)가 많이 수행되는 테이블은 정기적으로 재생성을 할 필요가 있다.

:——————————————————————————————————

  • 인덱스를 경유한 검색

  • lmc는 브랜치 블럭의 첫 번째 로우의 값보다 적은 값을 갖는 하위의 블럭의 주소정보(dba:data block address)를 말한다.
  1. 루트 블록을 찾는다.
  2. 주어진 값보다 같거나 최소값을 찾는다.(찾는값 >= 인덱스값)
  3. 찾는 값 < 인덱스 값 (Lmc에 있는 dba로 이동)
  4. 찾는 값 = 인덱스 값 (해당 dba로 이동)
  5. 찾는 값 > 인덱스 값 (검색 후 찾는 값 = 인데스 값이면 해당 dba로 이동 그렇지 않으면, 찾는 값 < 인데스 값을 만족하는 인덱스 최소값)
  6. 리프 블록을 찾을 때까지 ② 의 단계를 반복해서 수행.
  7. 리프 블록에서 주어진 값을 가진 키를 찾아 존재하면 ROWID를 이용해 테이블을 액세스하고, 그렇지 않으면 'No Data found'로 결과 반환 만약, col2의 조건을 'ACC'가 아닌 'AC%'로 바꾸면 Col1 = 'B'이면서 Col2 = 'AC'보다 같거나 큰 것에서 스캔을 시작, 'AD' 보다 작으면 테이블을 액세스하고, 그렇지 않으면 종료한다.

:——————————————————————————————————

B-tree인덱스의 문제점

  • B-TREE인덱스에서는 실제 컬럼 값을 인덱스에도 보관하고 있어야 한다는 점이 대용량 데이터를 관리할 때 부담이 된다.
  • B-TREE인덱스 컬럼값의 분포도가 좋아야 한다는 점
  • 결합인덱스에서 조건을 사용하지 않는 컬럼이나 =조건이 아닌 컬럼이 결합인덱스 중간에 있으면 액세스효율성이 떨어진다는 점
  • 다양한 액세스패턴을 수용하기 위해 많은 인덱스가 필요할 수 있다는 점
  • NOT이나 NULL을 사용하거나 복잡한 OR조건에서는 인덱스의 성능을 보장받지 못한다는 점

2.2 비트맵(Bitmap) 인덱스

  • 컴퓨터에서 사용하는 최소의 단위인 비트를 사용하여 컬럼 값을 저장하고 이를 이용하여 rowid를 자동으로 생성하는 인덱스 방법으로 비트를 직접 관리하므로 저장공간이 감소하고 비트연산이 용이 하다는 장점이 있다.
  • 생성 명령어 : CREATE BITMAP INDEX … ON …

2.2.1 비트맵(Bitmap) 인덱스의 탄생 배경

  • B-TREE인덱스가 가지는 문제점을 독립적으로 구성된 각각의 비트맵 인덱스가 조합되어 해결할 수 있다.

2.2.2 비트맵(Bitmap) 인덱스의 구조와 특성

구조

  • 루트 블록이나 브랜치 블록은 B-tree인덱스와 같은 구조로 되어 있으나 리프블록은 비트맵으로 구성되어 있다.

생성절차

  1. 인덱스를 생성하고자 하는 컬럼의 값들을 찾기 위해 테이블 스캔을 한 후
  2. bitmap generator에 의해 컬럼값, start rowid, end rowid , bitmap을 갖는 인덱스 엔트리를 생성한다.
  3. 2단계에서 생성된 Bitmap들을 B-tree구조에 넣기 쉽도록 key값과 start rowid 순으로 정렬한다.
  4. 마지막 단계에서는 정렬된 인덱스 엔트리들을 단순히 B-tree구조로 삽입한다.

특성

  • 비트를 저장할 때는 '선분 형태(Start rowid ~ End rowid)'로 저장을 하므로 일종의 압축 개념이 되며, 키 압축(Key Compression)이 적용되어 저장 공간이 매우 절약된다.
  • 비트맵 연산을 통해 처리하므로 OR 연산이 가능하다.
  • NULL 값도 BIT를 구성하고 있어 NULL 및 NOT 조건검색이 가능하다.
  • 수정이 빈번하게 발생하는 컬럼은 인덱스의 크기가 크게 증가하고 블록레벨 잠금(Block Level Locking)으로 인해 많은 부하가 유발될 수 있다.
  • 데이터 웨어하우스 업무에 주로 활용된다.

제한사항

  • Partition table에서 Global Index에는 Bitmap Index를 만들 수 없다.
  • Local Index를 구성할 경우에는 Bitmap Index로 만들 수 있으나, 여러 파티션에 걸쳐있는 Global Index를 구성할 때는 Bitmap Index를 만들 수 없다.
  • Bitmap Index는 RBO(rule base optimizer) mode에서는 사용될 수 없다.
  • Bitmap Index는 통계치에 의하여 산출된 cost를 기반으로 Bitmap Index의 사용여부를 결정하기 때문에 Optimizer Mode는 반드시 CBO(cost based optimizer) Mode인 ALL_ROWS 또는 FIRST_ROWS로 지정되거나 , CHOOSE mode인 경우 해당 object는 ANALYZE 명령을 통하여 통계정보를 생성해 주어야 한다.
  • IOT(Index Organized Table)에는 rowid를 가지고 있지 않기 때문에 rowid range로 표현되는 Bitmap Index를 사용할 수 없다. 그러나 Oracle9i부터는 ALTER TABLE .. MOVE MAPPING TABLE과 같이 mapping table을 이용하여 Bitmap Index를 사용할 수 있다.

2.2.3 비트맵(Bitmap) 인덱스의 엑세스

비트맵 인덱스 사용시 실행계획 오퍼레이션

NOT,OR 이 포함된 쿼리에 실행계획

  1. COL1 인덱스에서 '123'인 비트맵을 엑세스하고,COL2인덱스에서 'ABC'인 비트맵을 엑세스하여 감산연산을 수행한다(BITMAP MINUS)
  2. COL2에서 NULL인 비트맵과 1의 결과를 다시 감산연산을 수행한다(BITMAP MINUS)
  3. COL3 < 100 인 비트맵을 읽어 머지(BITMAP MERGE)를 수행하여 하나의 비트맵을 만든다.
  4. 23에서 수행한 결과에 대해 OR연산(BITMAP OR)을 수행하여 조건을 만족하는 최종결과 비트맵을 만들고 ROWID로 변형하여 테이블을 엑세스 한다.
  • 제한사항
    • 파티션테이블에서 Global Index에는 비트맵인덱스를 만들 수 없다.
    • 비트맵인덱스는 RBO(Rule Base optimizxer) mode에서는 사용될 수 없다.

B-Tree 인덱스와 비트맵(Bitmap)인덱스의 비교

  • OLTP : 네트워크상의 여러 이용자가 실시간으로 데이터베이스의 데이터를 갱신하거나 조회하는 등의 단위 작업을 처리하는 방식
study/oracle/datadb/1week_2.1273122353.txt.gz · 마지막으로 수정됨: 2010/05/06 14:05 저자 ahmax