ClickHouse의 테이블 파티션이란 무엇인가요?
파티션은 MergeTree 엔진 계열에서 테이블의 데이터 파트를 체계적이고 논리적인 단위로 묶습니다. 이는 시간 범위, 범주, 기타 주요 속성 등 특정 기준에 따라 데이터를 개념적으로 의미 있게 구성하는 방식입니다. 이러한 논리적 단위는 데이터를 더 쉽게 관리하고, 쿼리하고, 최적화할 수 있게 해줍니다.
PARTITION BY
PARTITION BY toStartOfMonth(date) 절을 추가해 확장합니다. 이렇게 하면 부동산 거래가 발생한 월을 기준으로 테이블의 데이터 파트가 구성됩니다:
디스크상의 구조
먼저 ClickHouse 서버는 위 다이어그램에 표시된 4개의 행으로 이루어진 예시 삽입의 행들을 파티션 키 값
toStartOfMonth(date)를 기준으로 분할합니다.
그런 다음 식별된 각 파티션에 대해 여러 순차적 단계(① 정렬, ② 컬럼으로 분할, ③ 압축, ④ 디스크에 쓰기)를 수행하여 행들을 일반적인 방식으로 처리합니다.
파티셔닝이 활성화되면 ClickHouse가 각 데이터 파트에 대해 MinMax 인덱스를 자동으로 생성한다는 점에 유의하십시오. 이는 파티션 키 표현식에 사용된 각 테이블 컬럼별 파일로, 해당 데이터 파트 내 그 컬럼의 최솟값과 최댓값을 담고 있습니다.
파티션별 머지
위 도식에서 보듯이, 서로 다른 파티션에 속한 파트는 절대 머지되지 않습니다. 카디널리티(cardinality)가 높은 파티션 키를 선택하면 파트가 수천 개의 파티션에 분산되어 머지 대상이 되지 못하고, 결국 미리 설정된 한도를 초과해 악명 높은
Too many parts 오류가 발생합니다. 이 문제를 해결하는 방법은 간단합니다. 카디널리티가 1000..10000 미만인 적절한 파티션 키를 선택하십시오.
파티션 모니터링
_partition_value를 사용하면 예시 테이블에 존재하는 모든 고유 파티션 목록을 쿼리할 수 있습니다:
또는 ClickHouse는 system.parts 시스템 테이블에서 모든 테이블의 모든 파트와 파티션을 추적하며, 다음 쿼리는 앞서 나온 예시 테이블에 대해 모든 파티션 목록과 함께 각 파티션별 현재 활성 파트 수와 해당 파트에 포함된 행 수의 합계를 반환합니다:
테이블 파티션은 어디에 사용되나요?
데이터 관리
toStartOfMonth(date)로 파티션되므로, TTL 조건을 충족하는 전체 파티션(테이블 파트의 집합)이 삭제되어 파트를 재작성하지 않고도 정리 작업을 더 효율적으로 수행할 수 있습니다.
마찬가지로, 오래된 데이터를 삭제하는 대신 자동으로 더 비용 효율적인 스토리지 티어로 효율적으로 이동할 수 있습니다:
쿼리 최적화
date)과 테이블의 프라이머리 키에 사용된 컬럼(town)을 모두 기준으로 필터링해 2020년 12월 런던에서 판매된 모든 부동산의 최고가를 계산합니다 (date는 프라이머리 키의 일부가 아닙니다).
ClickHouse는 관련 없는 데이터를 처리하지 않기 위해 일련의 프루닝 기법을 적용하여 이 쿼리를 수행합니다:
① 파티션 프루닝: MinMax 인덱스를 사용해 테이블의 파티션 키에 사용된 컬럼에 대한 쿼리 필터와 논리적으로 일치할 수 없는 전체 파티션(파트 집합)을 제외합니다. ② 그래뉼 프루닝: ①단계 후 남아 있는 데이터 파트에 대해서는 프라이머리 인덱스를 사용해 테이블의 프라이머리 키에 사용된 컬럼에 대한 쿼리 필터와 논리적으로 일치할 수 없는 모든 그래뉼(행 블록)을 제외합니다. 이러한 데이터 프루닝 단계는 앞서 살펴본 예시 쿼리의 물리적 쿼리 실행 계획을 EXPLAIN 절로 확인하면 관찰할 수 있습니다:
date 필드의 MinMax index를 사용해, 기존 활성 데이터 파트 436개 중 1개에 저장된 기존 그래뉼 3257개(행 블록) 중 11개를 식별하고, 이 그래뉼들에 쿼리의 date 필터와 일치하는 행이 포함되어 있음을 보여줍니다.
② 그래뉼 프루닝: 위 EXPLAIN 출력의 19행부터 24행까지를 보면 ClickHouse가 이어서 ① 단계에서 식별된 데이터 파트의 프라이머리 인덱스(town 필드에 생성됨)를 사용해, 쿼리의 town 필터와도 일치할 가능성이 있는 행을 포함한 그래뉼 수를 11개에서 1개로 더 줄인다는 것을 알 수 있습니다. 이는 위에서 출력한 쿼리 실행 시의 ClickHouse-client 출력에도 반영되어 있습니다.
파티셔닝은 주로 데이터 관리 기능입니다
uk_price_paid_simple_partitioned에는 600개가 넘는 파티션이 있으므로 활성 데이터 파트도 600 306개에 달합니다. 반면 파티셔닝되지 않은 테이블 uk_price_paid_simple에서는 모든 초기 데이터 파트가 백그라운드 머지를 통해 하나의 활성 파트로 머지될 수 있었습니다.
위의 예시 쿼리를 파티션 필터 없이 파티셔닝된 테이블에 대해 실행할 때의 물리적 쿼리 실행 계획을 EXPLAIN 절로 확인해 보면, 아래 출력의 19행과 20행에서 ClickHouse가 기존 그래뉼 3257개 중 671개(행 블록)를 식별했음을 알 수 있습니다. 이 그래뉼들은 쿼리 필터와 일치하는 행을 잠재적으로 포함하며, 기존 활성 데이터 파트 436개 중 431개에 걸쳐 분포해 있습니다. 따라서 이들은 쿼리 엔진에 의해 스캔되고 처리됩니다.