Blog
kudupartitioningperformance

Apache Kudu 파티셔닝 완전 가이드: Hash, Range, 그리고 Multilevel 전략

Kudu 테이블의 Hash Partitioning, Range Partitioning, Multilevel Partitioning 전략을 실제 예제와 함께 비교하고, Partition Pruning 동작 원리와 설계 시 주의사항을 정리합니다.

Data Dynamics2026년 4월 13일20 min read

Apache Kudu 에서 테이블을 생성할 때 파티셔닝은 선택이 아닌 필수 입니다. Kudu 는 기본 파티셔닝 전략을 제공하지 않으므로, 테이블을 만들 때 반드시 파티셔닝 방식을 명시해야 합니다. 잘못된 파티셔닝은 쓰기 핫스팟, 읽기 성능 저하, 무한정 커지는 tablet 등 다양한 문제를 유발합니다. 이 글은 Kudu 공식 Schema Design 문서의 Partitioning 섹션 을 바탕으로, 각 파티셔닝 전략의 특성과 실무 적용법을 정리합니다.

1. 파티셔닝의 기본 개념

Kudu 테이블은 tablet 이라는 단위로 분할되어 여러 Tablet Server 에 분산 저장됩니다. 하나의 row 는 항상 하나의 tablet 에만 속하며, 어떤 row 가 어떤 tablet 에 배치되는지는 테이블 생성 시 정의한 파티셔닝 전략에 의해 결정됩니다.

파티셔닝 전략은 테이블 생성 이후에는 변경할 수 없습니다 (Range Partition 의 추가/삭제만 예외). 따라서 설계 시점에 신중한 결정이 필요합니다.

Kudu 가 제공하는 파티셔닝 방식은 크게 세 가지입니다:

파티셔닝 방식설명
Hash PartitioningPrimary Key 컬럼의 해시값으로 bucket 에 분배
Range PartitioningPrimary Key 컬럼의 값 범위로 연속적인 구간에 분배
Multilevel PartitioningHash + Range 또는 Hash + Hash 를 조합

이 글에서는 Kudu 공식 문서에서 사용하는 metrics 테이블 예제를 기반으로 각 전략을 설명합니다.

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time)
);

이 테이블은 여러 호스트에서 수집되는 시계열 메트릭 데이터를 저장합니다. host, metric, time 의 조합이 Primary Key 이며, 파티셔닝 전략에 따라 성능이 크게 달라집니다.

2. Range Partitioning

2.1 동작 원리

Range Partitioning 은 정렬된 범위(range) 를 기준으로 row 를 분배합니다. 각 파티션은 키 공간의 연속적인 구간을 담당합니다. Range Partition 의 컬럼은 반드시 Primary Key 의 부분 집합 이어야 합니다.

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time)
)
PARTITION BY RANGE (time) (
    PARTITION VALUE = 1,
    PARTITION VALUE = 2,
    PARTITION VALUE = 3
)
STORED AS KUDU;

2.2 장점

  • 시간 기반 스캔 최적화: 시간 범위 조건이 있는 쿼리는 해당 범위에 속하지 않는 파티션을 자동으로 건너뜀 (Partition Pruning)
  • 동적 파티션 관리: 런타임에 파티션을 추가하거나 삭제할 수 있으며, 다른 파티션의 가용성에 영향을 주지 않음
  • 효율적인 데이터 삭제: 파티션을 삭제하면 해당 파티션의 모든 데이터가 함께 삭제됨. row 단위 DELETE 후 compaction 을 기다릴 필요 없이 즉시 디스크 공간 회수 가능

2.3 단점

  • 쓰기 핫스팟: 시계열 데이터의 경우 현재 시점의 데이터가 항상 하나의 파티션에 집중됨. 이로 인해 특정 Tablet Server 에 쓰기 부하가 몰림
  • 병렬성 제한: 쓰기가 하나의 tablet 에 집중되면 다른 Tablet Server 의 자원이 유휴 상태로 낭비됨

핵심: Range Partitioning 단독 사용은 읽기에는 유리하지만 쓰기에는 불리 합니다. 시계열 데이터에서 Range 만 사용하면 최신 데이터 파티션이 핫스팟이 됩니다.

3. Hash Partitioning

3.1 동작 원리

Hash Partitioning 은 지정된 컬럼의 해시값 을 기반으로 row 를 여러 bucket 에 분배합니다. bucket 수는 테이블 생성 시 결정되며 이후 변경할 수 없습니다. Primary Key 컬럼의 부분 집합을 해시 대상으로 사용할 수 있습니다.

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time)
)
PARTITION BY HASH (host, metric) PARTITIONS 8
STORED AS KUDU;

3.2 장점

  • 쓰기 분산: 해시 함수가 row 를 고르게 분배하므로 쓰기 핫스팟이 발생하지 않음
  • 균등한 tablet 크기: 데이터가 bucket 간에 고르게 분포
  • 특정 host/metric 조회 최적화: hostmetric 에 대한 동등 조건(equality predicate) 이 있으면 Partition Pruning 가능

3.3 단점

  • tablet 무한 성장: Range Partition 처럼 파티션을 추가/삭제할 수 없으므로, 데이터가 계속 쌓이면 tablet 이 무한정 커짐
  • 시간 범위 조회 비효율: time 컬럼이 해시에 포함되지 않았으므로 시간 범위 조건만으로는 Partition Pruning 이 불가능
  • 데이터 삭제 비용: 오래된 데이터를 삭제하려면 row 단위 DELETE 를 수행해야 하며, 실제 디스크 공간은 compaction 이 완료될 때까지 회수되지 않음

핵심: Hash Partitioning 단독 사용은 쓰기에는 유리하지만 tablet 의 무한 성장이 문제 입니다. 장기간 운영 시 tablet 크기가 감당할 수 없을 만큼 커질 수 있습니다.

4. Multilevel Partitioning (Hash + Range 조합)

4.1 동작 원리

Kudu 는 여러 단계의 파티셔닝을 하나의 테이블에 조합 할 수 있습니다. 0개 이상의 Hash Partition 레벨과 선택적인 Range Partition 레벨을 함께 사용할 수 있습니다. 전체 tablet 수는 각 레벨의 파티션 수를 곱한 값 입니다.

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time)
)
PARTITION BY
    HASH (host, metric) PARTITIONS 8,
    RANGE (time) (
        PARTITION VALUE = 1,
        PARTITION VALUE = 2,
        PARTITION VALUE = 3
    )
STORED AS KUDU;

이 예제에서 전체 tablet 수는 8 (Hash buckets) x 3 (Range partitions) = 24개 입니다.

4.2 Hash + Range 의 장점

이 조합은 Hash 와 Range 각각의 장점을 결합하고 단점을 보완합니다.

관점Hash 단독Range 단독Hash + Range
쓰기 분산균등 분산핫스팟 발생균등 분산
시간 범위 읽기Pruning 불가Pruning 가능Pruning 가능
특정 host/metric 읽기Pruning 가능Pruning 불가Pruning 가능
tablet 성장 관리무한 성장동적 추가/삭제동적 추가/삭제
오래된 데이터 삭제row 단위 DELETE 필요파티션 DROP 으로 즉시 삭제파티션 DROP 으로 즉시 삭제
  • 쓰기: Hash 가 hostmetric 을 기준으로 여러 bucket 에 분산하므로, 같은 시간대의 쓰기도 여러 tablet 에 병렬로 처리됨
  • 읽기: 시간 범위 조건으로 Range Partition Pruning, host/metric 동등 조건으로 Hash Partition Pruning 이 동시에 동작
  • 관리: 오래된 Range Partition 을 DROP 하면 해당 시간 범위의 데이터가 즉시 삭제되고 디스크 공간이 회수됨

4.3 Hash + Hash 조합

Hash 를 여러 단계로 조합하는 것도 가능합니다. 단, 서로 다른 Hash 레벨이 같은 컬럼을 해시해서는 안 됩니다.

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time)
)
PARTITION BY
    HASH (host) PARTITIONS 4,
    HASH (metric) PARTITIONS 4
STORED AS KUDU;

이 경우 전체 tablet 수는 4 x 4 = 16개 입니다.

Hash + Hash 조합의 특징:

  • 쓰기가 모든 tablet 에 골고루 분산됨
  • 그러나 Range Partition 이 없으므로 tablet 이 무한정 성장 하고, 오래된 데이터를 파티션 단위로 삭제할 수 없음
  • 단일 Hash 레벨에서 모든 컬럼을 해시하는 것보다 핫스팟에 약간 더 취약할 수 있음

권장: 시계열 데이터에는 Hash + Range 조합 을 사용하세요. Hash + Hash 는 시간 기반 데이터 관리가 필요 없는 경우에만 적합합니다.

5. Flexible Partitioning (Range 별 Hash 스키마)

Kudu 1.17 이상부터는 Range 파티션별로 서로 다른 Hash 스키마 를 적용할 수 있습니다. 이를 통해 특정 Range 구간에서 발생하는 핫스팟을 더 세밀하게 제어할 수 있습니다.

예를 들어, 최근 데이터는 Hash bucket 수를 많이 잡아 쓰기를 분산하고, 오래된 데이터는 Hash bucket 수를 줄여 tablet 수를 절약하는 전략이 가능합니다.

단, 주의할 점이 있습니다: 모든 Range 에서 Hash Partition 레벨의 수(단계 수)는 동일해야 합니다. bucket 수는 다를 수 있지만, Hash 레벨 자체의 개수는 맞춰야 합니다.

6. Partition Pruning (파티션 가지치기)

Partition Pruning 은 Kudu 의 핵심 성능 최적화 메커니즘입니다. 스캔 시 조건(predicate)에 의해 특정 파티션이 완전히 필터링될 수 있으면, 해당 파티션의 tablet 을 아예 스캔하지 않습니다.

6.1 Pruning 조건

파티셔닝 방식Pruning 이 동작하는 조건
Hash Partition해시에 사용된 모든 컬럼 에 대한 동등 조건(equality predicate) 이 있어야 함
Range PartitionRange 컬럼에 대한 동등 조건 또는 범위 조건(range predicate) 이 있어야 함
Multilevel각 레벨에 대해 독립적으로 Pruning 가능

6.2 Pruning 예제 (Hash + Range)

HASH (host, metric) PARTITIONS 8, RANGE (time) 파티셔닝이 적용된 metrics 테이블에서:

쿼리 조건Hash PruningRange Pruning효과
WHERE host = 'a' AND metric = 'cpu' AND time >= 100 AND time < 200가능 (8→1 bucket)가능 (해당 범위만)최적 — 소수의 tablet 만 스캔
WHERE host = 'a' AND metric = 'cpu'가능 (8→1 bucket)불가Hash Pruning 만 동작
WHERE time >= 100 AND time < 200불가가능 (해당 범위만)Range Pruning 만 동작
WHERE host = 'a'불가 (metric 조건 없음)불가Pruning 없음 — full scan

중요: Hash Partition Pruning 은 해시에 포함된 모든 컬럼에 대한 동등 조건이 있어야만 동작합니다. 하나라도 빠지면 Pruning 이 불가능합니다.

7. 파티셔닝 전략 비교 요약

공식 문서에서 제시하는 metrics 테이블 기준 비교를 확장하면:

전략쓰기 성능읽기 성능tablet 성장 관리데이터 삭제Pruning
RANGE (time)나쁨 (핫스팟)좋음 (시간 Pruning)좋음 (동적 관리)좋음 (DROP)Range 만
HASH (host, metric)좋음 (분산)좋음 (host/metric Pruning)나쁨 (무한 성장)나쁨 (row DELETE)Hash 만
HASH (host, metric) + RANGE (time)좋음 (분산)좋음 (양쪽 Pruning)좋음 (동적 관리)좋음 (DROP)양쪽 모두
HASH (host) + HASH (metric)좋음 (분산)제한적나쁨 (무한 성장)나쁨 (row DELETE)Hash 만

8. 실무 설계 가이드라인

8.1 tablet 수 결정

테이블 생성 시 tablet 수는 다음 공식으로 결정됩니다:

총 tablet 수 = Hash bucket 수 × Range partition 수

읽기/쓰기 부하가 높은 테이블은 최소한 Tablet Server 수 이상의 tablet 을 갖도록 설계하여 부하가 모든 서버에 분산되도록 합니다.

클러스터 규모최소 권장 tablet 수Hash bucket 수 예시
Tablet Server 3대3개 이상4 또는 8
Tablet Server 5대5개 이상8
Tablet Server 10대10개 이상8 또는 16

8.2 Hash Partition 설계 시 고려사항

  1. Hash 컬럼 선택: 카디널리티가 높은 컬럼을 선택해야 데이터가 bucket 간에 고르게 분포됨
  2. bucket 수: 일반적으로 Tablet Server 수의 배수로 설정. 너무 많으면 tablet 수 폭증, 너무 적으면 병렬성 부족
  3. 변경 불가: Hash bucket 수는 테이블 생성 후 변경할 수 없으므로 신중하게 결정

8.3 Range Partition 설계 시 고려사항

  1. 파티션 단위: 일별보다 월별 파티션 을 우선 검토. 일별 파티션은 tablet 수를 30배 증가시킴
  2. 미래 파티션: 미리 대량으로 생성하지 말고, 필요한 시점에 동적으로 추가
  3. 데이터 보관 정책: 오래된 파티션을 DROP 하면 즉시 디스크 공간 회수 가능. row 단위 DELETE 보다 훨씬 효율적
  4. 비어 있는 파티션: 데이터가 없는 Range Partition 도 tablet 을 유지하므로 WAL 디스크를 소비함

8.4 디스크 공간 회수에 대한 이해

Kudu 에서 row 단위로 데이터를 DELETE 하면, 삭제된 row 가 차지하던 디스크 공간은 compaction 이 완료될 때까지 즉시 회수되지 않습니다. 대량의 과거 데이터를 삭제해야 하는 경우, Range Partition 을 사용하여 파티션 단위로 DROP 하는 것이 디스크 공간을 즉시 회수하는 유일한 방법입니다.

-- 비효율적: row 단위 삭제 → 디스크 공간은 compaction 후에야 회수
DELETE FROM metrics WHERE time < 1000;
 
-- 효율적: 파티션 단위 삭제 → 즉시 디스크 공간 회수
ALTER TABLE metrics DROP RANGE PARTITION VALUE = 1;

9. 파티셔닝 설계 체크리스트

항목확인
파티셔닝 전략을 명시적으로 정의했는가? (Kudu 는 기본 파티셔닝을 제공하지 않음)
시계열 데이터라면 Hash + Range 조합을 사용했는가?
Hash 컬럼으로 카디널리티가 높은 컬럼을 선택했는가?
Hash bucket 수가 Tablet Server 수의 배수에 가까운가?
Range Partition 단위로 일별 대신 월별을 검토했는가?
전체 tablet 수 (Hash buckets × Range partitions) 가 Tablet Server 당 1,000개 이하인가?
오래된 데이터 삭제 전략이 Range Partition DROP 기반인가?
미래 Range Partition 을 과도하게 미리 생성하지 않았는가?
Partition Pruning 이 주요 쿼리 패턴에서 동작하는지 확인했는가?
Hash Pruning 을 위한 동등 조건이 쿼리에 포함되는가?

10. 정리

항목내용
기본 파티셔닝제공되지 않음 — 반드시 명시적으로 설계
권장 조합 (시계열)Hash + Range
Hash Partition 변경불가능 (bucket 수, 컬럼 모두)
Range Partition 변경추가/삭제만 가능
Hash Pruning 조건해시 컬럼 전체 에 대한 동등 조건 필수
Range Pruning 조건Range 컬럼에 대한 동등 또는 범위 조건
tablet 수 공식Hash buckets × Range partitions
디스크 공간 즉시 회수Range Partition DROP 만 가능 (row DELETE 는 compaction 후)
Flexible PartitioningKudu 1.17+ 에서 Range 별 Hash bucket 수 다르게 설정 가능

파티셔닝은 Kudu 테이블 설계에서 가장 중요한 결정 입니다. 한 번 정하면 바꿀 수 없고 (Range 추가/삭제 제외), 쓰기/읽기 성능, 데이터 관리, 디스크 사용량 모두에 직접적인 영향을 미칩니다. 테이블을 만들기 전에 쿼리 패턴, 데이터 증가율, 보관 정책을 충분히 분석하고, Hash + Range 조합을 기본 전략으로 검토하세요.


이 글은 Apache Kudu 공식 Schema Design Guide — Partitioning 을 참고하여 작성되었습니다. Kudu 파티셔닝 설계나 운영에 대해 도움이 필요하시면 언제든 문의해 주세요.

— Data Dynamics 엔지니어링 팀