컴퓨터에서 사용하는 최소단위인 비트를 이용하여 컬럼값을 저장하고 이를 이용하여 ROWID를 자동으로 생성하는 인덱스의 한 방법이다.
비트를 직접 관리하므로 저장공간이 크게 감소하고 비트연산을 수행할 수 있다는 이점이 있다.
B-TREE인덱스가 가지는 문제점을 독립적으로 구성된 각각의 비트맵 인덱스가 조합되어 해결할 수 있다.
B-Tree Index는 테이블 Column값과 집합 내에서 해당정보의 rowid를 정렬된 형태로 가지는 구조이므로 동일 값에 대해서 물리적 주소가 다른 경우 동일 값을 중복해서 가지고 있어야 함으로 저장공간의 낭비가 발생하게 된다.
또한 테이블 Column값의 길이가 큰 경우 Index의 원시 값을 그대로 가짐으로써 Index의 크기가 증가하게 된다.
B-Tree Index에서는 동일한 테이블에 대한 Access시에 두 개 이상의 Index를 병행해서 사용하는 데에 많은 제약사항이 따른다. 그러나 실제 업무 환경에서는 사용자의 요구 사항은 매우 다양하다. 이러한 요구사항을 만족하기 위해서는 테이블의 모든 컬럼의 조합만큼의 B-tree Index를 만들어야 하며, 이렇게 한다고 하면 테이블의 크기보다 오히려 Index의 크기가 더 커지는 기현상을 초래할 수 있다. 또한, 각각의 인덱스를 관리하는 비용이 테이블 자체를 관리하는 비용보다 커질 수 있을 것이다. 따라서 실제 업무에는 거의 적용하기 불가능한 경우라고 할 수 있겠다.
분포도가 좋은 두개의 B-Tree Index가 있을 경우 두개 이상의 인덱스를 동시에 사용하는데 하나만 사용되고 체크조건으로 사용되는 등 두개의 인덱스를 효과적으로 사용하기 위한 제약사항이 있다.
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구조로 삽입한다.
DML작업시 계속적으로 BitMap 엔트리가 커지므로 빈번한 DML작업은 Bitmap Index의 크기가 Table보다 커지게 하는 결과를 초래 할 수 있다. 그러므로 OLTP 환경에서 Bitmap Index가 부적절하며 Index Rebuild 작업의 필요성이 커진다.
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)으로 인식하여 저장하게 되므로 인덱스를 사용할 수 있다.
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'를 추출하면 되기 때문이다.
create bitmap index idx_emp_name on emp(Ename);
alter index idx_emp_name rebuild online;
ORA-08108: 인덱스 온라인으로 된 유형을 구축하거나 재구축하지 말아야 합니다
{column}
{section}
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}
테이블에 하나의 bitmap index가 존재할 때 optimizer는 b-tree index를 사용하여 bitmap access path를 사용할지를 고려한다.
이때 생성되는 access path는 b-tree와 bitmap을 결합한 형태가 될수 있으며, bitmap을 전혀 포함하지 않을 수는 없다.
Row Source | Description |
---|---|
BITMAP CONVERSION TO ROWIDS | BITMAP을 TABLE를 ACCESS하기 위해 사용할 실제적인 ROWID로 변환한다. |
BITMAP CONVERSION FROM ROWIDS | ROWID를 BITMAP 형태로 변환한다. |
BITMAP CONVERSION COUNT | TABLE ACCESS가 필요없을 경우에 BITMAP에서 ROWID의 수를 COUNT한다. |
BITMAP INDEX SINGLE VALUE | single key value에 해당하는 bitmap을 검색한다. |
BITMAP INDEX RANGE SCAN | Key Value가 어떤 범위에 있는 bitmap을 검색한다 |
BITMAP INDEX FULL SCAN | bitmap index 전체를 검색한 다. |
BITMAP MERGE | RANGE 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 연산을 하지 않아도 된다.