파티셔닝 키 선택하기

파티셔닝 키 선택하기

파티셔닝은 주로 데이터 관리 기법이지 쿼리 최적화 도구가 아닙니다. 이 문서에서는 파티셔닝 키를 어떻게 신중하게 골라야 하는지, 특히 낮은 카디널리티 키가 왜 중요한지 설명할게요.

출처: 문서

본문

데이터 관리 기법 파티셔닝은 주로 데이터 관리 기법이지 쿼리 최적화 도구가 아닙니다. 특정 워크로드에서는 성능을 향상시킬 수 있지만, 쿼리를 가속화하는 첫 번째 수단이 되어서는 안 됩니다. 파티셔닝 키는 그 영향력을 명확히 이해한 상태에서 신중하게 선택해야 하며, 데이터 수명 주기 요구 사항이나 잘 이해된 접근 패턴과 맞을 때만 적용해야 합니다.

ClickHouse에서 파티셔닝은 지정된 키를 기준으로 데이터를 논리적 세그먼트로 구성합니다. 이는 테이블 생성 시점에 PARTITION BY 절로 정의되며, 시간 간격, 카테고리, 또는 기타 비즈니스 관련 차원으로 행을 그룹화하는 데 흔히 사용됩니다. 파티셔닝 표현식의 각 고유 값은 디스크에 고유한 물리적 파티션을 형성하며, ClickHouse는 이 값들 각각에 대해 별도의 파트에 데이터를 저장합니다. 파티셔닝은 데이터 관리를 개선하고, 보존 정책을 단순화하며, 특정 쿼리 패턴에 도움을 줍니다. 예를 들어 다음 UK 부동산 가격 데이터셋 테이블은 파티셔닝 키로 toStartOfMonth(date)를 사용합니다.

CREATE TABLE uk.uk_price_paid_simple_partitioned
(
  date Date,
  town LowCardinality(String),
  street LowCardinality(String),
  price UInt32
)
ENGINE = MergeTree
ORDER BY (town, street)
PARTITION BY toStartOfMonth(date)

테이블에 행 집합이 삽입될 때마다 ClickHouse는 삽입된 전체 행을 담은 (최소한) 하나의 데이터 파트를 만드는 대신(여기에서 설명), 삽입된 행 중 고유한 파티션 키 값마다 새 데이터 파트를 하나씩 만듭니다. ClickHouse 서버는 먼저 삽입된 행들을 파티션 키 값 toStartOfMonth(date)에 따라 분할합니다. 그런 다음 식별된 각 파티션에 대해 행들을 평소처럼 여러 순차 단계(① 정렬, ② 컬럼 분할, ③ 압축, ④ 디스크 쓰기)로 처리합니다. 파티셔닝에 대한 더 자세한 설명은 이 가이드를 추천합니다. 파티셔닝이 활성화되면 ClickHouse는 파티션 내에서만, 파티션 간에는 머지를 하지 않습니다. 위 예제 테이블에 대해 이를 간단히 그려 보겠습니다.

파티셔닝의 활용

파티셔닝은 특히 관측성(observability)과 분석 사용 사례에서 대규모 데이터셋을 관리하는 강력한 도구입니다. 데이터 수명 주기 작업을 효율적으로 수행할 수 있게 해 주는데, 보통 시간이나 비즈니스 로직에 맞춰 정렬된 전체 파티션을 단일 메타데이터 작업으로 drop, 이동, 또는 아카이브할 수 있기 때문입니다. 이는 행 단위 삭제나 복사 작업보다 훨씬 빠르고 리소스 부담도 적습니다. 파티셔닝은 TTL이나 티어드 스토리지(tiered storage) 같은 ClickHouse 기능과도 깔끔하게 연동되어, 커스텀 오케스트레이션 없이도 보존 정책이나 핫/콜드 스토리지 전략을 구현할 수 있습니다. 예를 들어 최근 데이터는 빠른 SSD 기반 스토리지에 두고, 더 오래된 파티션은 자동으로 더 저렴한 오브젝트 스토리지로 옮길 수 있습니다. 파티셔닝이 일부 워크로드에서 쿼리 성능을 향상시킬 수는 있지만, 응답 시간에 부정적 영향을 줄 수도 있습니다. 파티셔닝 키가 프라이머리 키에 없고 그 컬럼으로 필터링한다면 파티셔닝 덕분에 쿼리 성능이 좋아질 수 있습니다. 예시는 여기를 참고하세요. 반대로 쿼리가 파티션을 가로질러 조회해야 한다면 전체 파츠 수가 많아져 성능이 나빠질 수 있습니다. 이런 이유로 사용자는 파티셔닝을 쿼리 최적화 기법으로 고려하기 전에 자신의 접근 패턴을 이해해야 합니다. 요약하면, 파티셔닝은 우선적으로 데이터 관리 기법으로 생각해야 합니다. 데이터 관리의 예시는 관측성 사용 사례 가이드의 “Managing Data”와 핵심 개념 - 테이블 파티션의 “What are table partitions used for?”를 참고하세요.

낮은 카디널리티 파티셔닝 키를 선택하세요

중요하게도, 파츠 수가 많을수록 쿼리 성능에 부정적인 영향을 줍니다. ClickHouse는 전체 또는 파티션별로 파츠 수가 지정된 한도를 초과하면 삽입에 대해 “too many parts” 오류로 응답합니다. 파티셔닝 키의 올바른 카디널리티를 선택하는 것은 매우 중요합니다. 고카디널리티 파티셔닝 키 — 고유 파티션 값의 수가 큰 경우 — 는 데이터 파츠가 급증하게 만듭니다. ClickHouse는 파티션을 가로질러 파츠를 머지하지 않으므로, 파티션이 너무 많으면 머지되지 않은 파츠가 너무 많아져 결국 “Too many parts” 오류를 일으킵니다. 머지는 저장 단편화를 줄이고 쿼리 속도를 최적화하는 데 필수적이지만, 고카디널리티 파티션에서는 그 머지 잠재력이 사라집니다. 반대로 저카디널리티 파티셔닝 키 — 고유 값이 100~1,000개 미만인 경우 — 가 보통 최적입니다. 파츠 머지를 효율적으로 만들고, 메타데이터 오버헤드를 낮게 유지하며, 스토리지에서 과도한 오브젝트 생성도 피합니다. 또한 ClickHouse는 파티션 컬럼에 MinMax 인덱스를 자동으로 구축하므로 해당 컬럼으로 필터링하는 쿼리를 크게 빨라지게 합니다. 예를 들어 toStartOfMonth(date)로 파티셔닝된 테이블에서 월 단위로 필터링하면 엔진이 관련 없는 파티션과 그 파츠를 통째로 건너뛸 수 있습니다. 파티셔닝이 일부 쿼리 패턴에서 성능을 향상시킬 수는 있지만, 주로 데이터 관리 기능입니다. 많은 경우 모든 파티션을 가로질러 조회하는 것은 데이터 단편화 증가와 더 많은 파츠 스캔 때문에 파티셔닝하지 않은 테이블보다 느릴 수 있습니다. 파티셔닝은 신중하게 사용하고, 선택한 키가 항상 낮은 카디널리티를 가지며 데이터 수명 주기 정책(예: TTL을 통한 보존)에 맞는지 확인하세요. 파티셔닝이 필요한지 확신이 없다면 일단 파티셔닝 없이 시작하고, 관찰된 접근 패턴에 따라 나중에 최적화해도 좋습니다.

더 알아보기 (Learn more)