Blog
kudupartitioninglimitation

Apache Kudu 테이블 설계 시 반드시 알아야 할 기능적 제약

파티션 개수, 컬럼 수 제한, Primary Key 설계 순서 등 Kudu 를 실무에서 운영할 때 놓치기 쉬운 제약 사항들을 정리합니다.

Data Dynamics2026년 4월 13일25 min read

Apache Kudu 는 빠른 분석 쿼리와 실시간 업서트를 동시에 지원하는 강력한 스토리지 엔진이지만, 테이블을 설계할 때 반드시 인지해야 할 기능적 제약 들이 존재합니다. 이 제약들을 무시하고 테이블을 만들면 디스크 공간 낭비, 성능 저하, 심지어 클러스터 불안정으로 이어질 수 있습니다. 이 글은 Kudu 공식 Known Issues and Limitations 문서Schema Design 가이드 를 바탕으로, 실무에서 놓치기 쉬운 제약 사항들을 정리합니다.

1. 파티션(Tablet) 개수 제한

Kudu 에서 테이블은 여러 개의 tablet 으로 분할되어 각 Tablet Server 에 분산 저장됩니다. 파티셔닝은 병렬 처리의 핵심이지만, 파티션 수를 무분별하게 늘리면 심각한 부작용이 발생합니다.

1.1 파티션당 고정 오버헤드

각 tablet 은 데이터가 없더라도 수 MB 의 디스크 공간 을 차지합니다. 이는 tablet 마다 유지되는 메타데이터, WAL(Write-Ahead Log), consensus 상태 정보 등 때문입니다.

항목대략적 크기
Tablet 메타데이터수백 KB ~ 수 MB
WAL 세그먼트 (최소 1개)수 MB
Consensus 메타데이터수십 KB
Bloom filter, Primary Key 인덱스데이터 양에 비례하지만 최소 크기 존재

예를 들어, hash partition 16개 x range partition 365개(1년 일별) = 5,840개 tablet 을 만들면, 데이터가 한 건도 없어도 수십 GB 의 디스크 공간 이 소모됩니다. 이것은 실제 데이터가 아니라 순수하게 파티션 메타데이터와 구조 유지 비용입니다.

1.2 권장 기준

Kudu 공식 문서에서 제시하는 가이드라인은 다음과 같습니다.

기준권장값
Tablet Server 당 tablet 수1,000개 이하 (이상적으로 수백 개)
테이블당 tablet 수클러스터 전체 Tablet Server 수 × 수십 개 이하
tablet 당 권장 데이터 크기1 GB ~ 10 GB

핵심 원칙: tablet 수를 늘려서 병렬성을 높이는 것보다, 적절한 크기의 tablet 을 유지하는 것 이 성능과 안정성 모두에 유리합니다.

1.3 파티션이 너무 많으면 생기는 문제

  • WAL 디스크 용량 폭증: 이 문제는 특히 심각합니다. 각 tablet 은 독립적인 WAL(Write-Ahead Log) 세그먼트를 유지하며, 데이터가 없는 빈 tablet 이라도 WAL 파일은 반드시 존재합니다. 파티션 수가 급격히 늘어나면 WAL 디스크 사용량이 실제 데이터 크기와 무관하게 기하급수적으로 증가 합니다. 초기 하드웨어 용량 산정 시 WAL 디스크를 데이터 디스크 대비 작게 잡는 경우가 많은데, 파티션 수가 예상보다 많아지면 WAL 디스크가 먼저 가득 차면서 새로운 테이블을 생성할 수 없거나 기존 테이블에 range partition 을 추가할 수 없는 상황 이 발생합니다. WAL 디스크 부족은 Tablet Server crash 로 이어질 수 있으므로, 하드웨어 용량 산정 시 클러스터 전체의 총 tablet 수를 기준으로 WAL 디스크 크기를 넉넉하게 계산 해야 합니다.
  • 디스크 공간 낭비: 빈 tablet 도 수 MB 씩 차지하므로, 파티션 수 자체가 디스크 소비의 주요 원인이 됨
  • 메모리 압박: 각 tablet 은 메모리 내에 MemRowSet, DeltaMemStore 등을 유지. tablet 수가 많아지면 Tablet Server 의 메모리가 부족해짐
  • Master 부하 증가: Kudu Master 는 모든 tablet 의 위치 정보를 관리. tablet 수가 지나치게 많으면 Master 의 heartbeat 처리와 tablet location lookup 이 느려짐
  • Compaction 경합: tablet 마다 독립적으로 compaction 이 수행되므로, tablet 이 많으면 I/O 경합이 심해짐
  • 리더 선출 폭풍: Tablet Server 재시작 시 수천 개의 tablet 이 동시에 리더 선출을 시작하면 클러스터 전체가 수 분간 불안정해짐
  • 클러스터 전체 성능 저하: 파티션 수가 전체 클러스터의 처리 능력을 초과하면 모든 테이블의 읽기/쓰기 성능이 동반 하락합니다. 이는 특정 테이블만의 문제가 아니라 클러스터에 존재하는 모든 테이블에 영향 을 미치는 심각한 문제입니다.

경고: 파티션 수 문제는 단일 테이블의 문제가 아닙니다. 클러스터 내 모든 테이블의 파티션 수 합계 가 Tablet Server 의 처리 한계를 결정합니다. 테이블 하나의 파티션을 과도하게 설계하면 다른 테이블의 성능까지 끌어내립니다.

1.4 일별 파티션 vs 월별 파티션: 파티션 단위 선택의 중요성

시계열 데이터를 다룰 때 range partition 을 일 단위 로 생성하는 것은 가장 흔한 실수 중 하나입니다. 일별 파티션이 가져오는 tablet 수 폭증을 구체적으로 비교해 보겠습니다.

파티션 전략Hash 8개 x Range 파티션 수1년간 tablet 수3년간 tablet 수
일별 파티션8 x 3652,9208,760
월별 파티션8 x 1296288

같은 테이블이라도 일별 vs 월별에 따라 30배의 tablet 수 차이 가 발생합니다. 테이블이 여러 개라면 이 차이는 배수로 커집니다.

시나리오 (테이블 5개, Hash 8, 3년 보관)일별 파티션월별 파티션
클러스터 전체 tablet 수43,8001,440
Tablet Server 5대 기준, 서버당 tablet 수8,760288
WAL 디스크 소비 (빈 tablet 포함)수백 GB수 GB

Tablet Server 당 권장 한계가 1,000개인 점을 감안하면, 일별 파티션 전략은 서버당 8,760개 로 권장치의 8.7배를 초과 합니다. 이는 클러스터를 불안정하게 만들고 WAL 디스크 부족으로 인한 장애를 유발합니다.

권장: 데이터를 반드시 일 단위로 조회해야 하는 경우가 아니라면, 월별 파티션을 기본 전략으로 채택 하세요. 일 단위 조회가 필요하더라도 Primary Key 에 날짜 컬럼이 포함되어 있다면 월별 파티션 내에서도 효율적인 scan pruning 이 가능합니다. 파티션 단위를 크게 잡는 것이 파티션을 잘게 쪼개는 것보다 거의 항상 안전합니다.

1.5 Range Partition 동적 관리

Range partition 은 ADD RANGE PARTITION / DROP RANGE PARTITION DDL 로 동적으로 추가/삭제할 수 있습니다. 시계열 데이터를 다룰 때는 미래 파티션을 미리 수백 개 만들어 두지 말고, 필요한 시점에 가까워지면 추가하고 오래된 파티션은 삭제 하는 전략이 효과적입니다.

-- 새 월별 파티션 추가
ALTER TABLE events ADD RANGE PARTITION VALUE = '2026-05';
 
-- 오래된 파티션 삭제 (해당 파티션의 모든 데이터도 함께 삭제됨)
ALTER TABLE events DROP RANGE PARTITION VALUE = '2024-01';

2. 컬럼 수 제한

2.1 하드 리밋과 소프트 리밋

Kudu 는 테이블당 최대 300개 의 컬럼을 지원합니다. 하지만 이것은 하드 리밋이고, 실질적으로는 그보다 훨씬 적은 수의 컬럼을 권장합니다.

구분컬럼 수
하드 리밋300개
소프트 리밋 (권장)수십 ~ 100개 이하

2.2 컬럼이 많아지면 생기는 문제

  • 스캔 성능 저하: Kudu 는 columnar storage 이므로 SELECT * 시 모든 컬럼의 데이터 블록을 읽어야 함. 컬럼이 많으면 I/O 양이 급증
  • RowSet compaction 비용 증가: compaction 시 모든 컬럼을 읽고 다시 써야 하므로 컬럼이 많을수록 CPU, I/O 비용이 커짐
  • 메타데이터 크기 증가: 스키마 정보가 모든 tablet 의 메타데이터에 포함되므로, 컬럼이 많으면 메타데이터도 커짐
  • 클라이언트 측 오버헤드: Impala 등 쿼리 엔진이 스키마를 가져올 때 지연 발생

: 컬럼이 200개 이상 필요한 경우, 테이블을 논리적으로 분리하거나 자주 함께 조회되는 컬럼 그룹별로 나누는 것을 검토하세요.

2.3 컬럼 수 하드 리밋 강제 증가 시 Crash 위험

Kudu 의 소프트 리밋을 우회하기 위해 --max_num_columns 플래그를 사용하여 컬럼 수 제한을 하드 리밋(300개)까지 강제로 올리는 경우가 있습니다. 이는 매우 위험한 행위 이며, 다음과 같은 심각한 문제를 유발할 수 있습니다.

  • Tablet Server Crash: 컬럼 수가 극단적으로 많아지면 각 tablet 의 RowSet 메타데이터, DeltaMemStore, Bloom filter 등이 비례하여 커집니다. Tablet Server 의 메모리 한계를 초과하면 OOM(Out of Memory) 으로 프로세스가 강제 종료 됩니다.
  • Compaction 실패: 컬럼이 매우 많은 tablet 의 compaction 은 CPU 와 메모리를 극도로 소비합니다. Compaction 도중 메모리 부족이 발생하면 tablet 이 compaction 불가 상태 에 빠지고, 이후 쓰기 성능이 급격히 저하됩니다.
  • 스키마 전파 장애: 컬럼이 수백 개인 테이블의 스키마를 모든 tablet 에 전파하는 과정에서 메타데이터 크기가 임계점을 넘으면 Master-Tablet Server 간 heartbeat 가 실패하여 tablet 이 unavailable 상태 가 될 수 있습니다.
  • 복구 불가능한 상태: 최악의 경우, 대량의 컬럼으로 인해 tablet 의 메타데이터 자체가 손상되면 해당 tablet 의 데이터를 복구할 수 없습니다.

경고: 소프트 리밋은 Kudu 개발팀이 안정적인 운영을 보장할 수 있는 범위를 기준으로 설정한 것입니다. --max_num_columns 값을 올려서 하드 리밋에 근접하게 컬럼을 생성하면, Kudu 스토리지 자체가 crash 되는 치명적인 장애 가 발생할 수 있습니다. 컬럼이 많이 필요한 경우 반드시 테이블을 분리하는 방법을 선택하세요.

3. Primary Key 설계

Kudu 의 Primary Key 는 단순히 유일성을 보장하는 것이 아니라, 데이터의 물리적 저장 순서 를 결정합니다. 따라서 Primary Key 의 컬럼 구성과 순서는 성능에 직접적인 영향을 미칩니다.

3.1 Primary Key 의 특성

특성설명
변경 불가테이블 생성 후 Primary Key 변경 불가 (컬럼 추가/삭제/순서 변경 모두 불가)
NOT NULL 필수Primary Key 컬럼은 반드시 NOT NULL
저장 순서 결정데이터는 Primary Key 의 바이트 순서로 정렬 저장
인덱스 역할Primary Key 는 자동으로 클러스터드 인덱스로 동작
타입 제한FLOAT, DOUBLE, BOOL 타입은 Primary Key 로 사용 불가

3.2 복합 Primary Key 에서 컬럼 순서가 중요한 이유

Kudu 는 Primary Key 의 prefix 를 기반으로 스캔 범위를 pruning 합니다. 이는 RDBMS 의 복합 인덱스와 동일한 원리입니다.

예를 들어, Primary Key 가 (region, timestamp, user_id) 인 테이블에서:

쿼리 조건Pruning 가능 여부
WHERE region = 'kr'가능 — 첫 번째 컬럼이므로 효율적
WHERE region = 'kr' AND timestamp >= '2026-04-01'가능 — prefix 순서대로 조건 사용
WHERE timestamp >= '2026-04-01'불가능 — 첫 번째 컬럼(region) 조건이 없으므로 full scan
WHERE user_id = 'abc'불가능 — prefix 를 건너뛰었으므로 full scan

3.3 Primary Key 컬럼 순서 설계 원칙

  1. 가장 자주 조건으로 사용되는 컬럼을 앞에 배치: 쿼리 패턴을 분석하여 WHERE 절에 가장 자주 등장하는 컬럼을 첫 번째로
  2. 카디널리티 고려: 카디널리티가 너무 낮은 컬럼(예: boolean)을 첫 번째에 놓으면 pruning 효과가 미미
  3. 쓰기 핫스팟 방지: 단조 증가하는 값(예: timestamp)을 첫 번째 컬럼에 놓으면 모든 쓰기가 마지막 tablet 에 집중됨
  4. Hash Partition 과의 조합: 핫스팟 방지를 위해 첫 번째 컬럼에 hash partition 을 적용하는 것이 일반적
-- 좋은 예: hash partition 으로 쓰기 분산 + range partition 으로 시계열 관리
CREATE TABLE events (
    event_id STRING NOT NULL,
    event_time TIMESTAMP NOT NULL,
    region STRING NOT NULL,
    payload STRING,
    PRIMARY KEY (event_id, event_time, region)
)
PARTITION BY
    HASH (event_id) PARTITIONS 8,
    RANGE (event_time) (
        PARTITION VALUE = '2026-04'
    )
STORED AS KUDU;
-- 나쁜 예: timestamp 가 첫 번째 컬럼이면서 hash 없이 range 만 사용
CREATE TABLE events (
    event_time TIMESTAMP NOT NULL,
    event_id STRING NOT NULL,
    region STRING NOT NULL,
    payload STRING,
    PRIMARY KEY (event_time, event_id, region)
)
PARTITION BY
    RANGE (event_time) (
        PARTITION VALUE = '2026-04'
    )
STORED AS KUDU;
-- 문제: 최신 데이터 쓰기가 하나의 tablet 에 집중 → 핫스팟 발생

3.4 Primary Key 컬럼 수 제한

Primary Key 를 구성하는 컬럼 수에는 명시적인 하드 리밋은 없지만, 컬럼 수가 많아지면 다음과 같은 부작용이 있습니다.

  • Primary Key 인덱스 크기 증가: 각 row 의 Primary Key 바이트가 커지면 인덱스가 메모리와 디스크를 더 많이 차지
  • 비교 연산 비용: Insert/Update/Delete 시 Primary Key 비교 비용이 증가
  • 스키마 유연성 감소: Primary Key 컬럼은 변경 불가이므로, 많이 포함할수록 스키마 변경의 여지가 줄어듦

권장: Primary Key 는 3~5개 이하의 컬럼 으로 구성하되, 반드시 쿼리 패턴과 파티셔닝 전략을 함께 고려하세요.

4. 기타 주요 제약 사항

4.1 데이터 타입 관련

제약설명
DECIMAL 정밀도최대 precision 38, scale 38. 금융 데이터 처리 시 주의
VARCHAR / STRING 최대 크기셀 단위 최대 64 KB
BINARY 최대 크기셀 단위 최대 64 KB
Primary Key 의 셀 크기 합계최대 16 KB
immutable 컬럼Primary Key 컬럼의 값은 INSERT 후 변경 불가

4.2 스키마 변경 관련

제약설명
Primary Key 변경불가능. 스키마 변경으로 PK 를 수정하거나 컬럼을 추가/삭제할 수 없음
컬럼 타입 변경불가능. 기존 컬럼의 데이터 타입을 변경할 수 없음
컬럼 이름 변경가능
컬럼 추가/삭제가능 (단, Primary Key 컬럼 제외)
파티션 스키마 변경불가능. Hash partition 의 bucket 수나 partition 컬럼 자체를 변경할 수 없음
Range partition 추가/삭제가능. 동적으로 범위 파티션 추가/삭제 가능

4.3 복제(Replication) 관련

제약설명
Replication Factor테이블 생성 시 지정, 이후 변경 불가. 홀수만 가능 (기본값 3)
최소 Tablet Server 수Replication Factor 이상의 Tablet Server 필요

4.4 Secondary Index

Kudu 는 secondary index 를 지원하지 않습니다. 따라서 Primary Key 가 아닌 컬럼으로 조회할 때는 full scan 이 발생합니다. Impala 와 함께 사용할 경우 Impala 의 실행 계획에 의존하게 되므로, Primary Key 와 파티셔닝 전략을 신중하게 설계해야 합니다.

4.5 멀티 로우(Multi-row) 트랜잭션

Kudu 는 단일 row 수준의 원자성(atomicity) 만 보장합니다. 여러 row 에 걸친 트랜잭션은 지원하지 않으므로, 여러 row 를 동시에 업데이트해야 하는 비즈니스 로직은 애플리케이션 레벨에서 보정해야 합니다.

4.6 테이블 수 제한

클러스터 전체에서 관리하는 테이블 수에는 명시적인 하드 리밋은 없지만, 테이블이 늘어나면 각 테이블의 tablet 수가 합산되므로 결과적으로 tablet 수 제한에 걸립니다. 테이블 수 x 테이블당 tablet 수 = 클러스터 전체 tablet 수 가 핵심 공식입니다.

5. 설계 체크리스트

테이블을 생성하기 전에 다음 항목을 확인하세요.

파티셔닝

  • Hash partition bucket 수가 Tablet Server 수의 배수에 가까운가?
  • Range partition 을 사용한다면 미래 파티션을 과도하게 미리 생성하지 않았는가?
  • 테이블당 전체 tablet 수 = Hash bucket 수 x Range partition 수 가 적정한가?
  • Tablet Server 당 총 tablet 수가 1,000개를 넘지 않는가?
  • 빈 tablet 으로 인한 디스크 낭비가 허용 범위인가?
  • WAL 디스크 용량이 전체 tablet 수를 감당할 수 있는가?
  • 일별 파티션 대신 월별 파티션을 사용할 수 있는지 검토했는가?
  • 클러스터 내 모든 테이블의 파티션 합계를 계산했는가?

컬럼 설계

  • 컬럼 수가 100개를 넘지 않는가? (넘는다면 테이블 분리 검토)
  • --max_num_columns 플래그를 강제로 올리지 않았는가? (crash 위험)
  • 불필요한 컬럼이 포함되지 않았는가?
  • STRING/BINARY 컬럼에 64 KB 를 초과하는 데이터가 들어올 가능성은 없는가?

Primary Key

  • Primary Key 컬럼 순서가 주요 쿼리 패턴과 일치하는가?
  • 단조 증가하는 값이 Primary Key 첫 번째 컬럼에 올 경우 Hash partition 을 적용했는가?
  • Primary Key 에 불필요하게 많은 컬럼을 넣지 않았는가?
  • Primary Key 셀 크기 합계가 16 KB 이하인가?
  • Primary Key 컬럼에 FLOAT, DOUBLE, BOOL 타입을 사용하지 않았는가?

운영

  • Replication Factor 를 적절히 설정했는가? (운영 환경에서는 3 권장)
  • 스키마 변경이 필요해질 가능성이 있다면 Primary Key 를 최소한으로 설계했는가?
  • Secondary Index 가 없다는 점을 고려하여 조회 패턴에 맞는 PK 를 구성했는가?

6. 정리

항목제약 / 권장
Tablet Server 당 tablet 수1,000개 이하 권장
빈 tablet 디스크 사용량tablet 당 수 MB (WAL 포함)
WAL 디스크파티션 수에 비례하여 증가 — 용량 산정 시 반드시 고려
파티션 단위 권장일별보다 월별 파티션 우선 검토
컬럼 수 하드 리밋 강제 증가Tablet Server crash 위험 — 절대 비권장
테이블당 최대 컬럼 수300개 (권장 100개 이하)
Primary Key 변경불가능
Primary Key 컬럼 타입 제한FLOAT, DOUBLE, BOOL 사용 불가
Primary Key 셀 크기 합계16 KB 이하
STRING/BINARY 셀 최대 크기64 KB
Secondary Index미지원
멀티 로우 트랜잭션미지원 (단일 row 원자성만 보장)
Range Partition 동적 관리지원 (ADD / DROP)
Hash Partition 변경불가능
Replication Factor 변경불가능

Kudu 는 설계 시점에 내린 결정이 운영 내내 영향을 미치는 스토리지 엔진입니다. 특히 Primary Key 와 파티셔닝 스키마는 한 번 정하면 바꿀 수 없기 때문에, 테이블을 만들기 전에 쿼리 패턴, 데이터 증가율, 클러스터 규모를 충분히 고려해야 합니다. "나중에 고치면 되지" 라는 접근은 Kudu 에서는 통하지 않습니다.


이 글은 Apache Kudu 공식 Known Issues and LimitationsSchema Design Guide 를 참고하여 작성되었습니다. Kudu 테이블 설계나 운영에 대해 도움이 필요하시면 언제든 문의해 주세요.

— Data Dynamics 엔지니어링 팀