2.2. 비트맵(Bitmap) 인덱스

컴퓨터에서 사용하는 최소단위인 비트를 이용하여 컬럼값을 저장하고 이를 이용하여 ROWID를 자동으로 생성하는 인덱스의 한 방법이다.
비트를 직접 관리하므로 저장공간이 크게 감소하고 비트연산을 수행할 수 있다는 이점이 있다.

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

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

B-Tree인덱스의 문제점

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

저장공간의 낭비

B-Tree Index는 테이블 Column값과 집합 내에서 해당정보의 rowid를 정렬된 형태로 가지는 구조이므로 동일 값에 대해서 물리적 주소가 다른 경우 동일 값을 중복해서 가지고 있어야 함으로 저장공간의 낭비가 발생하게 된다.
또한 테이블 Column값의 길이가 큰 경우 Index의 원시 값을 그대로 가짐으로써 Index의 크기가 증가하게 된다.

유연성(Flexibility)의 부족

B-Tree Index에서는 동일한 테이블에 대한 Access시에 두 개 이상의 Index를 병행해서 사용하는 데에 많은 제약사항이 따른다. 그러나 실제 업무 환경에서는 사용자의 요구 사항은 매우 다양하다. 이러한 요구사항을 만족하기 위해서는 테이블의 모든 컬럼의 조합만큼의 B-tree Index를 만들어야 하며, 이렇게 한다고 하면 테이블의 크기보다 오히려 Index의 크기가 더 커지는 기현상을 초래할 수 있다. 또한, 각각의 인덱스를 관리하는 비용이 테이블 자체를 관리하는 비용보다 커질 수 있을 것이다. 따라서 실제 업무에는 거의 적용하기 불가능한 경우라고 할 수 있겠다.
분포도가 좋은 두개의 B-Tree Index가 있을 경우 두개 이상의 인덱스를 동시에 사용하는데 하나만 사용되고 체크조건으로 사용되는 등 두개의 인덱스를 효과적으로 사용하기 위한 제약사항이 있다.

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

비트맵인덱스의 구조

B-tree의 leaf block은 Index key value + Rowid 로 구성이 되어 있지만, Bitmap Index는 Index key value + Start Rowid + End Rowid + Bitmap 엔트리로 구성되어 있다. 1개의 index값이 테이블상의 여러 개의 record를 표현하기 때문에 DML문을 사용할 경우 row level locking을 지원할 수 없다
Start Rowid 와 End Rowid 의 Range사이에 있는 모든 row수만큼 Bitmap이 표현되어야 하지만, 오라클에서는 내부적인 압축 알고리즘을 사용하여 Bitmap을 생성하기 때문에 모두 표현되지 않는 경우도 있다

비트맵인덱스 생성 절차

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

비트맵인덱스와 관련된 초기화 파라미터

  • CREATE_BITMAP_AREA_SIZE
    Bitmap Index를 생성하기 위한 memory의 양을 결정하는 parameter로 cardinality가 클수록 크게 설정을 해야 performance를 낼 수 있다.
    default 는 8M이다. 이 parameter는 system이나 session level에서 변경할 수 없다.
  • BITMAP_MERGE_AREA_SIZE
    Index range scan으로부터 탐색된 Bitmap Index는 Single Bitmap Index로 병합하기 전에 저장을 해야 하는데 이때 필요한 memory의 양을 결정 하는 parameter로 Bitmap Index를 통한 검색시에 성능에 밀접한 영향을 미치게 된다. cardinality 가 낮은 속성들을 결합하여 Bitmap Index를 생성하게 되면, 경우의 수가 증가하여 Bitmap Index을 검색하는 COST가 증가하게 된다. 뿐만 아니라 모든 조건이 Equal로 주어지지 않으면 range scan으로 Bitmap Index를 검색하여 검색된 모든 bitmap에 대하여 연산을 수행하므로 성능이 저하될 수밖에 없다. 이 parameter 또한 system이나 session level에서 변경할 수 없다.
  • SORT_AREA_SIZE
    BITMAP INDEX는 DML operation당 한번만 갱신되므로 insert 혹은 update의 performance를 향상시키기 위해서 SORT_AREA_SIZE를 효과적으로 설정해야 한다. SORT_AREA_SIZE는 user processor당 모두 할당되므로 너무 큰 값을 설정하게되면 전체 resource의 낭비를 초래하여 오히려 performance를 저하시킬 수 있기 때문이다

비트맵 인덱스의 특성

DML작업시 계속적으로 BitMap 엔트리가 커지므로 빈번한 DML작업은 Bitmap Index의 크기가 Table보다 커지게 하는 결과를 초래 할 수 있다. 그러므로 OLTP 환경에서 Bitmap Index가 부적절하며 Index Rebuild 작업의 필요성이 커진다.

  • Null 값 비교도 Bitmap Index를 사용한다
    {section}
    {column:width=300}

create bitmap index idx_emp_comm_bit on emp(comm);
;
select * from emp where comm is not null;

SELECT STATEMENT	CHOOSE								
  TABLE ACCESS(FULL) SCOTT.EMP									
;
select /*+ index(emp idx_emp_comm_bit) */  * 
  from emp where comm is not null;

SELECT STATEMENT	CHOOSE	40.084	4	348					
  TABLE ACCESS(BY INDEX ROWID) SCOTT.EMP		40.084	4	348				
    BITMAP CONVERSION(TO ROWIDS)									
      BITMAP INDEX(FULL SCAN) SCOTT.IDX_EMP_COMM_BIT

{column}
{section}
위와 같은 경우 B-Tree Index에서는 인덱스를 구성하고 있는 컬럼 값이 Null인 경우에는 저장하지 않는다.
Bitmap에서는 Null 또한 하나의 값(0이나1)으로 인식하여 저장하게 되므로 인덱스를 사용할 수 있다.

  • Not Equal 비교도 Bitmap Index를 사용한다
    {section}
    {column:width=300}

select * from emp where comm <> 0;

SELECT STATEMENT	CHOOSE								
  TABLE ACCESS(FULL) SCOTT.EMP									
;
select /*+ index(emp idx_emp_comm_bit) */  * 
  from emp where comm != 0;

SELECT STATEMENT	CHOOSE	40.084	4	348					
TABLE ACCESS(BY INDEX ROWID) SCOTT.EMP		40.084	4	348				
  BITMAP CONVERSION(TO ROWIDS)									
    BITMAP INDEX(FULL SCAN) SCOTT.IDX_EMP_COMM_BIT	

{column}
{section}
기존 B-Tree Index에서는 NOT EQUAL 비교 연산을 수행할 때 인덱스를 사용할 수 없다.
그러나 Bitmap index의 경우는 읽어야 할 범위가 EQUAL로 들어 왔을 때와 비슷하다.
EQUAL 연산의 경우는 bit 값이 '1'인 것을 추출하면 되고, NOT EQUAL의 경우는 '0'를 추출하면 되기 때문이다.

  • Online Rebuild작업 미지원
    Bitmap인덱스는 Online Rebuild작업도 지원하지 않는 운영상의 단점이 있다.
    {section}
    {column:width=300}

create bitmap index idx_emp_name on emp(Ename);
alter index idx_emp_name rebuild online;
ORA-08108: 인덱스 온라인으로 된 유형을 구축하거나 재구축하지 말아야 합니다

{column}
{section}

제한사항

  • 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 명령을 통하여 통계정보를 생성해 주어야 한다.
  • RI(Referencial Integrity) 및 Unique Constraints Check도 보장할 수 없다
    1개의 Bitmap index entry가 table상의 여러 건을 표현할 수 있기 때문이다
  • IOT(Index Organized Table)에서 사용할 수 없다
    IOT(Index Organized Table)에는 rowid를 가지고 있지 않기 때문에 rowid range로 표현되는 Bitmap Index를 사용할 수 없다. 그러나 Oracle9i부터는 ALTER TABLE .. MOVE MAPPING TABLE과 같이 mapping table을 이용하여 Bitmap Index를 사용할 수 있다.
    {section}
    {column:width=300}

   IOT(Index Organized Table)에서 사용할 수 없다

CREATE TABLE iottab
(test_id VARCHAR2(5),
title_name VARCHAR2(150),
author VARCHAR2(20),
contents VARCHAR2(2048),
status VARCHAR2(2),
CONSTRAINT pk_testiot PRIMARY KEY (test_id) )
ORGANIZATION INDEX
TABLESPACE tbs_1
PCTTHRESHOLD 20
INCLUDING contents
OVERFLOW TABLESPACE indx;

create bitmap index iot_bit_idx on iottab(author );
ora-28669 맵핑테이블이 없는 iot테이블에 비트맵인덱스를 생성할 수 없음.

맵핑테이블 선언
alter table iottab move mapping table tablespace tbs_1;

비트맵 인덱스가 생성됨
create bitmap index iot_bit_idx on iottab(author );

{column}
{section}

2.2.3 비트맵인덱스의 액세스

테이블에 하나의 bitmap index가 존재할 때 optimizer는 b-tree index를 사용하여 bitmap access path를 사용할지를 고려한다.
이때 생성되는 access path는 b-tree와 bitmap을 결합한 형태가 될수 있으며, bitmap을 전혀 포함하지 않을 수는 없다.

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

Row SourceDescription
BITMAP CONVERSION TO ROWIDSBITMAP을 TABLE를 ACCESS하기 위해 사용할 실제적인 ROWID로 변환한다.
BITMAP CONVERSION FROM ROWIDSROWID를 BITMAP 형태로 변환한다.
BITMAP CONVERSION COUNTTABLE ACCESS가 필요없을 경우에 BITMAP에서 ROWID의 수를 COUNT한다.
BITMAP INDEX SINGLE VALUEsingle key value에 해당하는 bitmap을 검색한다.
BITMAP INDEX RANGE SCANKey Value가 어떤 범위에 있는 bitmap을 검색한다
BITMAP INDEX FULL SCANbitmap index 전체를 검색한 다.
BITMAP MERGERANGE SCAN으로 도출된 여러 개의 BITMAP을 하나의 BITMAP으로 병합한다.
BITMAP MINUS한 bitmap의 bit를 다른 bitmap의 bit로부 터 뺀다.
BITMAP OR두 bitmap의 비트열에 대한 OR 연산을 수행
BITMAP AND두 bitmap의 비트열에 대한 AND 연산을 수행
BITMAP KEY ITERATION한 테이블에서 얻은 각각의 로우들을 특정 비트맵 인덱스에 대해 연속해서 탐침해서 해당 비트맵을 찾는 것 뒤에 비트멥 머지가 수행되어 하나의 비트맵으로 합쳐지며 스타 변형조인에서 나타나는 형태

비트맵 조인인덱스

Oracle9i부터는 하나의 테이블에 대한 비트맵 인덱스뿐만 아니라 비트맵 조인 인덱스(BJI : Bitmap Join Index)도 지원한다.
{section}
{column:width=300}


CREATE BITMAP INDEX emp_dept_loc 
  ON emp (dept.loc)
  FROM emp, dept
  WHERE emp.deptno = dept.deptno
  TABLESPACE tbs_1;
 
SELECT /*+ INDEX(emp emp_dept_loc) */ emp.empno, emp.ename
  FROM emp, dept
 WHERE emp.deptno = dept.deptno
   AND dept.loc ='CHICAGO';

SELECT STATEMENT	CHOOSE	14	5	95					
  HASH JOIN		14	5	95					
    TABLE ACCESS(FULL) SCOTT.DEPT	ANALYZED	2	1	9					
      TABLE ACCESS(BY INDEX ROWID) SCOTT.EMP	ANALYZED	10.736	3.75	37.5				
        BITMAP CONVERSION(TO ROWIDS)									
          BITMAP INDEX(SINGLE VALUE) SCOTT.EMP_DEPT_LOC	

{column}
{section}

비트맵 조인 인덱스의 특징

비트맵 조인인덱스는 많은 수의 Dimension 테이블을 가지는 Star Schema일 경우에 유용할 수 있다.
비트맵 조인인덱스를 사용할 경우 일반적인 비트맵 인덱스만을 사용할 때 발생하는 Bitwise 연산을 하지 않아도 된다.

비트맵 조인 인덱스의 장점

  • 비트맵 조인 인덱스는 두 개 이상의 테이블의 조인 결과에 대해 비트맵 인덱스를 생성할 수 있게 해준다
  • 비트맵 조인 인덱스는 조인되어야 하는 데이타의 양을 미리 제한 하여 디스크 공간을 효율적으로 사용할 수 있다??
  • 비트맵 조인 인덱스의 경우 Fact 테이블의 Rowid를 압축하여 유지하므로 훨씬 적은 양의 디스크 공간을 사용한다.
  • 많은 수의 Dimension 테이블을 가지는 Star Schema일 경우에 유용하다. 즉, 비트맵 조인 인덱스를 사용할 경우 일반적인 비트맵 인덱스만을 사용할 때 발생하는 Bitwise 연산을 하지 않아도 된다.

비트맵 조인 인덱스의 단점

  • 다양한 질의를 처리하기 위해서는 많은 수의 비트맵 조인 인덱스를 생성하여야 한다. 즉, 각 Dimension 테이블마다 인덱스를 생성하는 것이 아니라 각 Dimension 테이블의 각 열마다 비트맵 조인 인덱스를 생성하여야 한다.
  • 하나의 테이블(Fact 테이블)에 많은 수의 인덱스를 생성하여야 하기 때문에 관리 비용이 많이 든다. 특히, Fact 테이블에 대한 변경 작업이 발생할 경우 더 많은 관리 비용이 든다.
  • 인덱스를 재생성할 경우 조인 작업을 동반하기 때문에 인덱스 생성 비용이 크다.

문서에 대하여

  • 이 문서는 오라클클럽 대용량 데이터베이스 스터디 모임에서 작성하였습니다.
  • 이 문서를 다른 웹 페이지에 게재할 경우에는 출처를 꼭 남겨 주세요
  • {*}이 문서의 내용은 이화식님의 새로쓴 대용량 데이터베이스 솔루션을 참고했습니다.*