426. 비트맵 인덱스 (Bitmap Index)

⚠️ 이 문서는 "남자이면서, 20대이면서, 서울에 사는 사람"처럼 조건이 많고 데이터 종류가 몇 개 없는(남/여) 컬럼들을 검색할 때, **B-Tree 인덱스를 쓰면 오히려 느려지는 한계를 극복하기 위해 데이터를 0과 1의 조합으로 압축하여 빛의 속도로 연산하는 '비트맵 인덱스'**를 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 데이터의 상태를 **0(아님)과 1(맞음)**이라는 비트(Bit)의 배열로 쫙 펼쳐서 저장하는 특수한 인덱스다.
  2. 사용 조건 (분포도 낮음): 성별(남/여), 혈액형(A/B/O/AB), 부서명처럼 나올 수 있는 값의 종류(Cardinality)가 아주 적을 때만 쓸 수 있다.
  3. 가치: AND, OR 같은 다중 조건 검색을 할 때 컴퓨터가 가장 잘하는 '비트 논리 연산'을 써서 결과를 순식간에 뽑아낸다. 주로 데이터 웨어하우스(DW) 환경에서 쓰인다.

Ⅰ. 개요: B-Tree가 바보가 되는 순간 (Context & Necessity)

1,000만 명의 회원 테이블에서 성별 컬럼에 B-Tree 인덱스를 걸었다고 치자. "성별이 남자인 사람 다 찾아줘!"

  • B-Tree 인덱스: "네! 찾아보니... 어... 500만 명이나 있네요?"
  • 이 500만 명의 주소를 가지고 디스크로 점프(Key Lookup, 423번 문서)를 500만 번 뛰어야 한다. (서버 터짐)

이렇게 **'값의 종류(Cardinality)가 적어서, 한 번 찾으면 너무 많은 데이터가 쏟아져 나오는 컬럼'**에는 B-Tree 인덱스를 걸면 오히려 풀 스캔보다 더 느려진다. (분포도가 나쁘다, 즉 10~15% 이상을 차지한다) 이 딜레마를 수학적으로 해결한 것이 비트맵 인덱스다.

📢 섹션 요약 비유: 비트맵 인덱스는 학교에서 **'체육대회 청기백기 들기'**와 같습니다. 반장(B-Tree)이 "남자애들 일어서!"라고 이름 부르는 대신, "남자애들 청기 들어! 20대 백기 들어!"라고 하면 운동장에 앉아있는 100만 명 중 청기와 백기를 동시에 든 사람만 0.1초 만에 눈으로 싹 골라낼 수 있습니다.


Ⅱ. 비트맵 인덱스의 작동 원리 ★

비트맵 인덱스는 내부적으로 01로 된 거대한 지도를 만든다.

ID이름성별지역
1철수서울
2영희부산
3민수서울

1. 인덱스 생성 (0과 1의 지도)

  • 성별 인덱스:
    • 남: [1, 0, 1] (1, 3번이 남자)
    • 여: [0, 1, 0] (2번이 여자)
  • 지역 인덱스:
    • 서울: [1, 0, 1]
    • 부산: [0, 1, 0]

2. 다중 조건 검색 (Bitwise AND 연산)

  • 질문: "남자(AND) 서울 사람 찾아줘!"
  • 연산: 컴퓨터는 하드디스크를 안 뒤지고, 아까 만든 0과 1의 지도 두 장만 꺼내서 겹쳐본다.
    • 남자 지도: [1, 0, 1]
    • 서울 지도: [1, 0, 1]
    • AND 결과: [1, 0, 1]
  • 0.0001초 만에 "1번과 3번 데이터다!"라는 결론을 내고, 딱 두 번만 디스크로 점프해서 가져온다. 속도가 사기적이다.

Ⅲ. 치명적 단점: 쓰기(Write) 락(Lock)의 지옥

비트맵 인덱스는 조회(SELECT)에는 신이지만, 삽입/수정(INSERT/UPDATE)에는 최악의 쥐약이다.

  • 만약 4번 회원이 새로 가입했다.
  • 성별 인덱스: [1, 0, 1, 0]으로 배열을 고쳐야 한다.
  • 문제는 배열을 고치는 아주 짧은 찰나에, **저 지도 전체에 엄청나게 넓은 락(Table-level Lock)**이 걸려버린다는 것이다.
  • 즉, 쇼핑몰에 손님이 한 명 가입할 때마다 다른 사람들은 조회조차 멈추게 된다.

그래서 비트맵 인덱스는 실시간으로 주문이 쏟아지는 OLTP(운영 DB) 환경에서는 절대 쓸 수 없다. 대신, 매일 밤 12시에 데이터를 쏟아붓고 낮에는 조회만 100만 번 일어나는 데이터 웨어하우스(OLAP - 321번 문서) 환경에서만 쓰이는 귀족 인덱스다.

┌──────────────────────────────────────────────────────────────┐
│           비트맵 인덱스의 비트 논리 연산(Bitwise AND) 시각화           │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ Q. "직급이 [대리]이면서, [개발팀]인 사람을 찾아라!"                   │
│                                                              │
│ [ 🗺️ 비트맵 인덱스 지도 ]                                        │
│ 직급(대리) 지도:  1  0  1  0  0  1  0  (1, 3, 6번이 대리)         │
│ 부서(개발팀)지도:  0  0  1  1  0  1  0  (3, 4, 6번이 개발팀)       │
│                ▼  ▼  ▼  ▼  ▼  ▼  ▼                           │
│ [ ⚡ AND 연산 ] :  0  0  1  0  0  1  0  ◀── 컴퓨터가 젤 잘하는 계산! │
│                                                              │
│ ★ 결론: 3번, 6번 사원을 가져오면 끝. (디스크 뒤질 필요도 없음)           │
└──────────────────────────────────────────────────────────────┘

Ⅳ. 결론

"인덱스의 선택은 데이터의 카디널리티(분포도)가 결정한다." 개발자가 "이 컬럼은 나이, 성별, 부서처럼 뻔한 값만 들어가니까 인덱스 걸면 빠르겠지?"라고 B-Tree 인덱스를 거는 순간, 그 DB는 풀 스캔보다 못한 최악의 성능을 보여주게 된다. 분포도(카디널리티)가 나쁜 컬럼들의 다중 조건 검색을 처리할 수 있는 유일한 무기는 비트맵 인덱스뿐이다. 데이터의 생김새(다양성)를 분석하지 않고 무지성으로 걸어대는 인덱스만큼 시스템을 망치는 독약은 없다.


📌 관련 개념 맵

  • 대척점 자료구조: B-Tree 인덱스 (422번 문서 - 고유한 값이 많은 PK 검색에 특화)
  • 사용 환경: OLAP, 데이터 웨어하우스 (DW - 321번 문서)
  • 제한 사항: OLTP (온라인 트랜잭션 처리) 환경에서는 성능 폭락
  • 핵심 조건 키워드: Low Cardinality (카디널리티 낮음), 분포도 낮음

👶 어린이를 위한 3줄 비유 설명

  1. B-Tree 인덱스는 1만 명의 얼굴을 일일이 기억하고 찾는 거라면, 비트맵 인덱스는 친구들에게 '안경 썼음=O, 안 썼음=X'라고 크게 팻말을 들게 하는 거예요.
  2. "안경 쓰고 모자 쓴 친구 나와!"라고 하면, 선생님은 팻말 두 개가 다 'O'인 친구만 쓱 골라내면 되니까 1초 만에 찾을 수 있죠.
  3. 하지만 누가 안경을 벗었다 썼다 할 때마다(데이터 수정) 반 전체가 팻말을 고쳐 쓰는라 시간이 오래 걸려서 멈춰 있어야 한다는 단점이 있답니다!