ClickHouse MergeTree 엔진
ClickHouse MergeTree 엔진 (MergeTree)
MergeTree 엔진과 ReplacingMergeTree, AggregatingMergeTree 같은 MergeTree 계열 엔진은 ClickHouse에서 가장 널리 쓰이고 가장 견고한 테이블 엔진이에요. 높은 데이터 수집(ingest) 속도와 대규모 데이터를 위해 설계됐어요. 삽입(INSERT)은 테이블 파트(parts)를 만들고, 백그라운드 프로세스가 다른 파트와 병합(merge)해요.
MergeTree 계열의 주요 특징은 아래와 같아요.
- 테이블의 기본 키가 각 테이블 파트 내부의 정렬 순서(클러스터형 인덱스)를 결정해요.
- 기본 키는 개별 행이 아니라 8192행짜리 블록(그래뉼, granule) 을 참조해요.
- 임의의 파티션 표현식으로 테이블을 파티셔닝할 수 있어요. 파티션 프루닝으로 쿼리 시 불필요한 파티션은 읽지 않아요.
- 여러 클러스터 노드로 데이터를 복제해 고가용성·장애 조치·무중단 업그레이드를 지원해요.
출처: https://clickhouse.com/docs/engines/table-engines/mergetree-family/mergetree
테이블 생성
CREATE TABLE 문으로 생성해요. ENGINE = MergeTree() 는 파라미터가 없어요.
CREATE TABLE t
(
CounterID UInt32,
EventDate Date,
...
)
ENGINE = MergeTree()
ORDER BY (CounterID, EventDate)
PARTITION BY toYYYYMM(EventDate)
주요 절
ENGINE— 엔진 이름과 파라미터.ENGINE = MergeTree().ORDER BY— 정렬 키. 컬럼명 또는 임의 표현식 튜플. 예:ORDER BY (CounterID + 1, EventDate). 기본 키를 지정하지 않으면 정렬 키가 기본 키가 돼요. 정렬이 필요 없다면ORDER BY tuple().PARTITION BY— 파티셔닝 키. 선택. 대부분은 필요 없고, 필요해도 월 단위보다 세밀하게 쓰지 않는 게 좋아요. 월 단위는toYYYYMM(date_column)사용.PRIMARY KEY— 정렬 키와 다를 때만 지정. 선택.SAMPLE BY— 샘플링 표현식. 기본 키에 포함돼 있어야 해요. 예:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID)).TTL— 행 보관 기간과 파트의 디스크·볼륨 간 자동 이동 규칙. 예:TTL date + INTERVAL 1 DAY. 타입은DELETE | TO DISK 'xxx' | TO VOLUME 'xxx' | GROUP BY.SETTINGS— 엔진별 설정. 예:index_granularity(기본값 8192).
데이터 저장
테이블은 기본 키로 정렬된 데이터 파트로 구성돼요. 데이터가 삽입되면 각각이 기본 키 순으로 정렬된 별도의 파트가 만들어지고, 파티션이 다른 데이터는 다른 파트로 분리돼요. 백그라운드에서 병합으로 저장 효율을 높여요.
- 파트는
Wide(컬럼별 파일) 또는Compact(모든 컬럼이 한 파일) 형식으로 저장돼요.min_bytes_for_wide_part,min_rows_for_wide_part설정이 기준을 정해요. - 각 파트는 논리적으로 그래뉼(granule)로 나뉘고, 그래뉼이 읽기의 최소 단위예요.
index_granularity,index_granularity_bytes설정으로 그래뉼 크기를 제한해요.
기본 키와 인덱스
기본 키가 (CounterID, Date)라고 하면:
CounterID in ('a','h')→ 마크 범위[0,3)와[6,8)만 읽어요.CounterID IN ('a','h') AND Date = 3→[1,3)와[7,8)만 읽어요.Date = 3→[1,10]범위.
인덱스가 전체 스캔보다 항상 효과적이에요. 희소 인덱스(sparse index)라서 같은 기본 키의 행을 여러 번 삽입할 수 있고, ClickHouse는 고유 기본 키를 요구하지 않아요. Nullable 타입을 기본 키·정렬 키에 쓰는 건 권장하지 않아요(allow_nullable_key 설정으로 허용).
기본 키 선택
- 기본 키 컬럼 수 제한은 없어요. 인덱스 성능과 압축률, 병합 로직에 영향이 있어요.
- 컬럼을 추가하면
(a,b)에c조건 쿼리가 있을 때 인덱스 성능과 압축률이 향상될 수 있어요. - 기본 키는 삽입 성능과 메모리 소비에 영향을 주지만,
SELECT성능에는 영향이 없어요. - 기본 키 없이
ORDER BY tuple()로 만들면 삽입 순서대로 저장돼요.