Ken
ClickHouse는 대용량 분석 쿼리에 최적화된 컬럼 스토어 데이터베이스입니다. 하지만 적절한 설정을 통해 Point Query(단일 행 조회) 성능도 크게 향상시킬 수 있습니다. 이 글에서는 index_granularity 설정의 원리와 ClickHouse Cloud에서의 실제 성능 테스트 결과를 공유합니다.
- 1. Index Granularity란?
- 1.1 기본 개념
- 1.2 MergeTree 데이터 구조
- 1.3 Sparse Index의 특징
- 2. Granularity가 쿼리 성능에 미치는 영향
- 2.1 Point Query 동작 원리
- 2.2 Granularity별 비교
- 2.3 Trade-off 분석
- 3. ClickHouse Cloud 실제 테스트
- 3.1 테스트 환경
- 3.2 테이블 메타데이터 비교
- 3.3 Point Query 성능 테스트 결과
- 3.4 IN Query 성능 테스트
- 4. 워크로드별 권장 설정
- 4.1 의사결정 플로우
- 4.2 권장 Granularity 가이드
- 4.3 최적화 구성 예시
- 5. 결론
- 핵심 요약
- 실무 적용 가이드
1. Index Granularity란?
1.1 기본 개념
ClickHouse의 MergeTree 엔진은 데이터를 **Granule(그래뉼)**이라는 단위로 관리합니다. index_granularity는 하나의 Granule에 포함되는 행(row)의 수를 정의하며, 기본값은 8,192입니다.
💡 핵심 포인트: Granule은 ClickHouse가 데이터를 읽는 최소 단위입니다. 단 1행만 필요하더라도 해당 행이 속한 Granule 전체를 읽어야 합니다.
1.2 MergeTree 데이터 구조
각 Granule의 첫 번째 Primary Key 값만 인덱스에 저장됩니다. 이것이 **Sparse Index(희소 인덱스)**입니다.
1.3 Sparse Index의 특징
장점:
- 인덱스 크기가 매우 작음 (메모리에 전체 로드 가능)
- 대용량 데이터에서도 빠른 범위 검색
- 쓰기 성능에 미치는 영향 최소화
특성:
- 정확한 행 위치가 아닌 Granule 위치를 찾음
- 최종 필터링은 Granule 내에서 수행
- Granule 크기 = 최소 I/O 단위
2. Granularity가 쿼리 성능에 미치는 영향
2.1 Point Query 동작 원리
200만 행 테이블에서 WHERE player_id = 500000 쿼리 실행 시:
2.2 Granularity별 비교
Granularity | 전체 Granule 수 | Point Query 시 읽는 행 | 효율성 |
256 | 7,813개 | 256행 | ⭐ 32x |
1,024 | 1,954개 | 1,024행 | 8x |
4,096 | 489개 | 4,096행 | 2x |
8,192 | 244개 | 8,192행 | baseline |
2.3 Trade-off 분석
항목 | 작은 Granularity (256) | 큰 Granularity (8192) |
Point Query I/O | ⭐ 매우 적음 | 많음 |
Index/Mark 파일 크기 | 크다 (+22%) | ⭐ 작다 |
Full Scan 성능 | 동일 | 동일 |
압축 효율 | 약간 감소 | ⭐ 최적 |
3. ClickHouse Cloud 실제 테스트
3.1 테스트 환경
- 플랫폼: ClickHouse Cloud (AWS ap-northeast-2)
- Engine: SharedMergeTree
- 데이터: 게임 플레이어 정보 200만 행
- 테이블: 동일 스키마, 다른 Granularity (256, 1024, 4096, 8192)
3.2 테이블 메타데이터 비교
테이블 | Granularity | Rows | 압축 크기 | Total Marks | 저장 증가율 |
player_g256 | 256 | 2,000,000 | 69.5 MB | 7,814 | +22.8% |
player_g1024 | 1,024 | 2,000,000 | 60.0 MB | 1,954 | +6.0% |
player_g4096 | 4,096 | 2,000,000 | 57.0 MB | 489 | +0.7% |
player_g8192 | 8,192 | 2,000,000 | 56.6 MB | 245 | baseline |
3.3 Point Query 성능 테스트 결과
테스트 쿼리: SELECT * FROM player_g{N} WHERE player_id = 500000
Granularity | Read Rows | Read Bytes | 효율성 |
256 | 256 | 30.9 KB | ⭐ 32x |
1024 | 1,024 | 122.7 KB | 8x |
4096 | 4,096 | 488.4 KB | 2x |
8192 | 8,192 | 977.1 KB | baseline |
✅ 결과: Granularity=256 설정에서 Point Query가 정확히 256행만 읽었습니다. 이론적 예상과 정확히 일치!
3.4 IN Query 성능 테스트
테스트 쿼리: WHERE player_id IN (100000, 300000, 700000, 1000000, 1500000)
Granularity | Read Rows | 비고 |
256 | 1,280 | 5개 Granule × 256 |
8192 | 40,960 | 5개 Granule × 8,192 |
4. 워크로드별 권장 설정
4.1 의사결정 플로우
4.2 권장 Granularity 가이드
워크로드 유형 | 권장 Granularity | 이유 |
OLTP-like Point Query | 256 ~ 512 | I/O 최소화 |
혼합 워크로드 | 1,024 ~ 2,048 | 균형 |
분석 쿼리 중심 | 8,192 (기본값) | 인덱스 오버헤드 최소화 |
대용량 로그 | 8,192 ~ 16,384 | 쓰기/압축 효율 |
4.3 최적화 구성 예시
CREATE TABLE optimized_player_lookup (
player_id UInt64,
player_name String,
character_level UInt16,
last_login_at DateTime64(3),
-- ... 기타 컬럼
-- Bloom Filter Index 추가 (선택적)
INDEX idx_player_bloom player_id TYPE bloom_filter(0.01) GRANULARITY 1
)
ENGINE = MergeTree()
ORDER BY player_id
SETTINGS index_granularity = 256;
5. 결론
핵심 요약
항목 | 내용 |
index_granularity | 데이터를 읽는 최소 단위 결정 |
Point Query 최적화 | Granularity 축소로 I/O 최대 32배 감소 |
Trade-off | 저장 공간 10~25% 증가 |
ClickHouse Cloud | 커스터마이징 완벽 지원 |
실무 적용 가이드
- 워크로드 분석: Point Query 비율 확인
- 테스트 우선: 프로덕션 전 벤치마크 수행
- 모니터링:
system.query_log의read_rows확인 - 점진적 적용: 새 테이블부터 적용 후 확대
🎯 결론: ClickHouse는 분석 DB이지만, index_granularity 튜닝으로 Point Query 성능도 충분히 확보할 수 있습니다.
활용 코드:
clickhouse-hols/workload/index-granularity-point-query at main · litkhai/clickhouse-hols
ClickHouse Hands-on Labs . Contribute to litkhai/clickhouse-hols development by creating an account on GitHub.
github.com
테스트 일자: 2025년 12월 25일
환경: ClickHouse Cloud (AWS ap-northeast-2, SharedMergeTree)