Parallel Replicas — 샤딩 없이 쿼리 하나를 여러 레플리카에 쪼개기
ClickHouse PREWHERE 및 Parallel Replicas 공식 문서 종합 (웹 리서치, 2026) — ClickHouse 공식 문서(sql-reference/statements/select/prewhere, deployment-guides/parallel-replicas) ClickHouse 공식 문서 Parallel replicas
이 모듈을 다 읽으면
- Parallel Replicas가 clickhouse-learn-06의 샤딩 기반 분산과 근본적으로 다른 지점을 설명할 수 있다
- 코디네이터 레플리카가 그래뉼 단위 작업을 동적으로 분배하는 방식을 설명할 수 있다
clickhouse-learn-06에서 다룬 Distributed 테이블 엔진의 샤딩 기반 분산 처리와 근본적으로 다른 접근으로, 샤딩 없이도 같은 데이터를 복제해 갖고 있는 여러 레플리카에 쿼리 하나를 그래뉼(granule) 단위로 쪼개 병렬 실행하는 Parallel Replicas를 정리한다.
샤딩이 아니라 그래뉼 단위로 나눈다
clickhouse-learn-06에서 다룬 Distributed 테이블은 데이터 자체를 여러 샤드로 나눠 저장해두고 쿼리를 각 샤드에 분산시키는 방식이다. Parallel Replicas는 이와 다르게, 샤딩 없이도 같은 데이터를 통째로 복제해 갖고 있는 여러 레플리카에 쿼리 '하나'를 그래뉼(테이블 데이터의 작은 조각) 단위로 쪼개 나눠 처리하게 한다 — 데이터를 물리적으로 쪼개 저장하지 않고도 읽기 쿼리 하나의 처리를 여러 레플리카로 수평 확장할 수 있다는 게 핵심 차이다.
핵심 포인트
- Distributed 테이블(샤딩): 데이터 자체를 여러 샤드로 나눠 저장, 쿼리를 각 샤드에 분산
- Parallel Replicas: 샤딩 없이 같은 데이터를 복제해 가진 여러 레플리카에 쿼리 하나를 그래뉼 단위로 쪼개 병렬 처리
코디네이터의 동적 작업 배정 — announce와 task stealing
쿼리를 받은 레플리카 중 하나가 코디네이터 역할을 맡아, 어떤 파트·그래뉼을 처리해야 하는지 분석한 뒤 다른 레플리카들에게 그래뉼 단위 작업을 배정한다. 각 레플리카는 자신이 실제로 갖고 있는 파트를 코디네이터에 알려(announcement) 코디네이터가 그 파트를 안 가진 레플리카에게 엉뚱하게 작업을 맡기지 않게 한다. 작업은 한꺼번에 다 배정되는 게 아니라, 레플리카가 자기 작업을 끝낼 때마다 코디네이터에 새 작업을 요청하는 동적 방식이라, 레플리카 간 성능 편차가 있어도 꼬리 지연(tail latency)이 줄어든다 — 느린 레플리카가 맡은 작업을, 먼저 끝낸 빠른 레플리카가 일관 해싱 기반으로 '훔쳐서'(task stealing) 대신 처리하는 방식까지 갖추고 있다.
핵심 포인트
- 코디네이터가 그래뉼 단위 작업을 배정, 각 레플리카는 자신이 가진 파트를 announce해 잘못된 배정을 방지
- 작업은 레플리카가 완료할 때마다 동적으로 재요청 — 느린 레플리카의 남은 작업을 빠른 레플리카가 일관 해싱 기반으로 훔쳐가는 task stealing으로 꼬리 지연을 줄임
한계 — 모든 쿼리에 유리한 건 아니다
복잡한 쿼리, 결과 집합이 작은 쿼리, CTE·JOIN·프로젝션이 섞인 쿼리, 고카디널리티 집계 등에서는 오히려 성능이 저하될 수 있다 — 조율(코디네이터-레플리카 통신) 자체의 오버헤드가 실제로 나눠 처리할 만큼 큰 작업량을 상쇄해버리기 때문이다. 그래서 parallel_replicas_min_number_of_rows_per_replica 같은 설정으로 너무 작은 쿼리에는 이 기능이 아예 적용되지 않도록 하한선을 두는 것이 실무적으로 중요하다.
핵심 포인트
- 복잡한 쿼리/작은 결과셋/CTE·JOIN·프로젝션 혼재/고카디널리티 집계 등에서는 조율 오버헤드가 이득을 상쇄해 오히려 성능 저하 가능
- parallel_replicas_min_number_of_rows_per_replica로 너무 작은 쿼리에는 적용 안 되게 하한선을 두는 것이 실무적으로 중요