해당 글은 전적으로 [ 꿈꾸는 개발자, DBA 커뮤니티 구루비 ] 에서 참고하였음을 밝힙니다. 개인 공부 및 기록을 위한 글입니다. 따라서 옮기는 과정에서 경어체는 모두 제거하였으며, 본인의 관점으로 글을 작성하였습니다. 상세하고 정돈된 내용은 하단에 참고링크를 보시길 바랍니다.


비트맵(Bitmap) 인덱스

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


탄생배경

- B-Tree 인덱스의 문제점으로 인한 탄생


B-Tree 인덱스의 문제점

  • 비트리 인덱스에서는 실제 컬럼 값을 인덱스에도 보관하고 있어야 한다는 점이 대용량 데이터를 관리할 때 부담

  • 비트리 인덱스 컬럼 값의 분포도가 좋아야 한다는 점

  • 결합 인덱스에서 조건을 사용하지 않는 컬럼이나 "=" 조건이 아닌 컬럼이 결합인덱스 중간에 있으면 액세스 효율성이 떨어진다는 점

  • 다양한 액세스 패턴을 수용하기 위해 많은 인덱스가 필요할 수 있다는 점

  • NOT 이나 NULL 을 사용하거나 복잡한 OR 조건에서는 인덱스의 성능을 보장받지 못한다는 점

    • 저장공간의 낭비
      - 비트리 인덱스는 테이블 컬럼값과 집합 내에서 해당 정보의 ROWID를 정렬된 형태로 가지는 구조이므로 동일 값에 대해서 물리적 주소가 다른 경우 동일 값을 중복해서 가지고 있어야 함으로 저장공간의 낭비가 발생한다.

    • 유연성 부족
      - 비트리 인덱스에서는 동일한 테이블에 대한 Access시에 두 개 이상의 인덱스를 병행해서 사용하는 데에 많은 제약사항이 따른다. 따라 모든 컬럼의 조합만큼의 비트리 인덱스를 만들어야 하며, 이렇게 한다고하면 테이블의 크기보다 오히려 인덱스의 크기가 커지는 현상이 나타난다.


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


상품 테이블에는 10개의 데이터가 존재한다. 그리고 색상으로는 RED, GREEN, BLUE 가 입력되어 있으며, 8번 상품에는 아무런 색상도 입력되어 있지 않다. NULL이다. 비트맵 인덱스를 살펴보면 키 값이 BLUE인 첫번째 행에서 4번째, 7번째, 9번째 비트가 1로 설정되어 있다. 따라서 이에 상응하는 테이블 레코드의 색상 값이 BLUE임을 확인할 수 있다. 

+) 비트리 인덱스의 리프 블록은 Index Key Value + ROWID로 구성되어있는 반면에, 비트맵 인덱스는 Index Key Value + Start RowID + End RowID + Bitmap 엔트리로 구성되어 있다. 

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

비트맵 인덱스 활용
  • 비트맵 인덱스는 성별처럼 Distinct Value 개수가 적을 때 저장효율이 매우 좋다. 그런 컬럼이라면 B*Tree 인덱스보다 훨씬 적은 용량을 차지하므로 인덱스가 여러 개 필요한 대용량 테이블에 유용하다.
  • 주로 다양한 분석관점(Dimension)을 가진 팩트성 테이블이 여기에 속한다. 반대로 DIstinct Value가 아주 많은 컬럼이라면 오히려 B*Tree 인덱스보다 많은 공간을 차지한다.
  • 하나의 비트맵 인덱스 단독으로는 쓰임새가 별로 없지만 여러 비트맵 인덱스를 동시에 사용할 수 있다는 특징 때문에 대용량 데이터 검색 성능을 향상시키는데 큰 효과를 발휘할 수 있다.
  • 두 개 이상 비트맵을 이용한 Bitwise AND 연산뿐만 아니라 Bitwise OR, Bitwise Not 연산도 가능하다.

1
2
3
4
5
6
7
8
// -- 상품 테이블의 "크기"와 "색상" 두 컬럼에 
// -- 각각 비트맵 인덱스가 있는 상태에서 아래와 같은 쿼리를 수행
 
SELECT 
    *
FROM 상품 
WHERE (크기 = "SMALL" or 크기 is null
AND 색상 = "GREEN";
cs

 

"크기" 컬럼 인덱스로부터 "SMALL" 과 "NULL"에 대한 비트맵을 읽고, "색상" 인덱스로부터 "GREEN"에 대한 비트맵을 읽거나 위의 그림과 같이 Bitwise 연산을 해볼 수 있다. 


- 비트맵 인덱스는 여러 인덱스를 동시에 활용할 수 있다는 장점 때문에 다양한 조건절이 사용되는, 특히 정형화되지 않은 임의 질의가 많은 환경에 적합하다.

- 비트맵 인덱스는 LOCK에 의한 DML 부하가 심한 것이 단점이다. 레코드 하나만 변경되덜도 해당 비트맵에 속한 모든 레코드에 LOCK이 걸린다.




Posted by doubler
,