파티션
PARTITION BY 절을 통해 지정합니다. 이 절에는 하나 이상의 컬럼에 대한 SQL 표현식을 포함할 수 있으며, 이 표현식의 결과에 따라 각 행이 어느 파티션으로 들어갈지가 결정됩니다.
데이터 파트는 디스크에서 각 파티션과 논리적으로 연결되며(공통 폴더 이름 접두사를 통해), 각 파티션별로 분리해서 쿼리할 수 있습니다. 아래 예시에서 기본 otel_logs 스키마(schema)는 toDate(Timestamp) 표현식을 사용해 일 단위로 파티셔닝됩니다. 행이 ClickHouse에 삽입되면 이 표현식이 각 행에 대해 평가되며, 그 결과에 해당하는 파티션으로 라우팅됩니다(해당 날짜의 첫 번째 행이면 파티션이 생성됩니다).
otel_logs 테이블이 일 단위로 파티셔닝되어 있다고 가정하겠습니다. 구조화된 로그 데이터셋이 적재되어 있다면, 여러 날짜의 데이터가 포함됩니다:
otel_logs_archive를 둘 수 있습니다. 데이터는 파티션 단위로 이 테이블로 효율적으로 이동할 수 있으며(이는 단순한 메타데이터 변경입니다).
INSERT INTO SELECT를 사용해 데이터를 새 대상 테이블에 다시 써야 하는 다른 기법과는 대조적입니다.
파티션 이동테이블 간 파티션 이동을 수행하려면 여러 조건을 충족해야 합니다. 특히 테이블의 구조, 파티션 키, 기본 키, 인덱스/프로젝션이 동일해야 합니다.
ALTER DDL에서 파티션을 지정하는 방법에 대한 자세한 내용은 여기에서 확인할 수 있습니다.이 기능은 설정
ttl_only_drop_parts=1을 사용할 때 TTL에서 사용됩니다. 자세한 내용은 TTL을 사용한 데이터 관리를 참조하십시오.활용 사례
- 계층형 아키텍처 - 데이터를 스토리지 계층 간에 이동(스토리지 계층 참조)하여 핫-콜드 아키텍처를 구축할 수 있습니다.
- 효율적인 삭제 - 데이터가 지정된 TTL에 도달했을 때(TTL을 사용한 데이터 관리 참조)
쿼리 성능
TTL(Time-to-live)을 사용한 데이터 관리
테이블 수준 TTL
ttl 키에서 지정합니다. 예:
h 사용을 권장하며, 값은 파티셔닝 기간에 맞춰 설정해야 합니다. 예를 들어 일(day) 단위로 파티셔닝하는 경우 24h, 48h, 72h처럼 일수의 배수로 지정하십시오. 이렇게 하면 예를 들어 ttl: 96h로 설정한 경우 테이블에 TTL 절이 자동으로 추가됩니다.
예약된 TTL위에서 설명한 것처럼 TTL은 즉시 적용되지 않고 일정에 따라 적용됩니다. MergeTree 테이블 설정
merge_with_ttl_timeout은 삭제 TTL이 있는 머지를 다시 수행하기 전까지의 최소 지연 시간을 초 단위로 설정합니다. 기본값은 14400초(4시간)입니다. 하지만 이는 최소 지연 시간일 뿐이며, TTL 머지가 트리거되기까지 더 오래 걸릴 수 있습니다. 값이 너무 낮으면 예정되지 않은 머지가 많이 수행되어 많은 리소스를 소비할 수 있습니다. TTL 만료는 ALTER TABLE my_table MATERIALIZE TTL 명령으로 강제할 수 있습니다.ttl_only_drop_parts=1 설정 사용을 권장합니다 ** (기본 스키마에 적용됨). 이 설정이 활성화되면 ClickHouse는 그 안의 모든 행이 만료된 경우 파트 전체를 삭제합니다. TTL이 적용된 행을 부분적으로 정리하는 대신(ttl_only_drop_parts=0일 때 리소스를 많이 사용하는 뮤테이션을 통해 수행됨) 전체 파트를 삭제하면 merge_with_ttl_timeout 시간을 더 짧게 설정할 수 있고 시스템 성능에 미치는 영향도 줄일 수 있습니다. 예를 들어 TTL 만료를 수행하는 단위(예: 일)와 동일한 단위로 데이터를 파티션하면, 파트에는 자연스럽게 정의된 인터벌의 데이터만 포함됩니다. 이렇게 하면 ttl_only_drop_parts=1을 효율적으로 적용할 수 있습니다.
컬럼 수준 TTL
Body 컬럼은 유지하는 것을 권장합니다. 예를 들어 1개월이 지나면 이러한 추가 메타데이터가 유용하지 않다는 점이 분명해질 수 있으므로, Body 컬럼을 계속 유지할 가치도 제한될 수 있습니다.
아래에서는 Body 컬럼을 30일 후에 삭제하는 방법을 보여줍니다.
컬럼 수준 TTL을 지정하려면 사용자 정의 스키마(schema)를 지정해야 합니다. 이 설정은 OTel collector에서는 지정할 수 없습니다.
데이터 재압축
ZSTD(1)를 권장하지만, ZSTD(3)처럼 다른 압축 알고리즘이나 더 높은 압축 수준을 시험해 볼 수도 있습니다. 이는 스키마(schema) 생성 시 지정할 수 있을 뿐만 아니라, 일정 기간이 지난 뒤 압축 설정이 변경되도록 구성할 수도 있습니다. 코덱 또는 압축 알고리즘이 압축 효율은 높이지만 쿼리 성능은 떨어뜨리는 경우, 이러한 방식이 적절할 수 있습니다. 이런 절충안은 쿼리 빈도가 낮은 오래된 데이터에는 수용 가능할 수 있지만, 문제 조사에서 더 자주 사용되는 최신 데이터에는 적합하지 않을 수 있습니다.
아래는 그 예시로, 데이터를 삭제하는 대신 4일 후 ZSTD(3)로 압축하는 방법을 보여줍니다.
성능 평가서로 다른 압축 수준과 알고리즘이 삽입 및 쿼리 성능에 미치는 영향을 항상 함께 평가하는 것이 좋습니다. 예를 들어, 델타 코덱은 타임스탬프 압축에 유용할 수 있습니다. 하지만 타임스탬프가 기본 키(primary key)의 일부이면 필터링 성능이 저하될 수 있습니다.
스토리지 계층
ClickHouse Cloud에는 해당되지 않음ClickHouse Cloud는 S3를 기반으로 하는 단일 데이터 사본을 사용하며, SSD 기반 노드 캐시를 함께 사용합니다. 따라서 ClickHouse Cloud에서는 스토리지 계층이 필요하지 않습니다.
ALTER TABLE MOVE PARTITION 명령으로 디스크 간에 수동 이동할 수 있으며, 볼륨 간 데이터 이동은 TTL을 사용해 제어할 수도 있습니다. 전체 예시는 여기에서 확인할 수 있습니다.
스키마 변경 관리
기본값 사용
DEFAULT 값을 사용해 스키마에 컬럼을 추가할 수 있습니다. INSERT 시 값이 지정되지 않으면 지정된 기본값이 사용됩니다.
이 새 컬럼이 전송되도록 materialized view 변환 로직이나 OTel collector 구성을 수정하기 전에 스키마를 먼저 변경할 수 있습니다.
스키마를 변경한 후에는 OTel collector를 다시 구성할 수 있습니다. 사용자가 “SQL로 구조 추출하기”에서 설명한 권장 프로세스를 사용한다고 가정하겠습니다. 이 프로세스에서는 OTel collector가 데이터를 Null table engine으로 전송하고, materialized view가 대상 스키마를 추출한 뒤 그 결과를 저장할 대상 테이블로 전달합니다. 이 경우 뷰는 ALTER TABLE ... MODIFY QUERY 구문을 사용해 수정할 수 있습니다. 예를 들어, OTel 구조화 로그에서 대상 스키마를 추출하기 위해 아래와 같은 대상 테이블과 그에 대응하는 materialized view(“SQL로 구조 추출하기”에서 사용한 것과 유사함)가 있다고 가정하겠습니다.
LogAttributes에서 새 컬럼 Size를 추출하려는 경우를 가정해 보겠습니다. 기본값을 지정해 ALTER TABLE로 이를 스키마에 추가할 수 있습니다:
LogAttributes의 size key로 지정합니다(존재하지 않으면 0이 됩니다). 즉, 값이 삽입되지 않은 행에서 이 컬럼에 접근하는 쿼리는 맵에 접근해야 하므로 더 느려집니다. 이 값은 상수(예: 0)로도 쉽게 지정할 수 있으며, 이렇게 하면 해당 값이 없는 행에 대한 후속 쿼리 비용을 줄일 수 있습니다. 이 테이블을 쿼리해 보면 값이 예상대로 맵에서 채워졌음을 확인할 수 있습니다:
ALTER TABLE 구문을 사용해 materialized view를 수정할 수 있습니다:
Size 컬럼 값이 삽입 시점에 채워집니다.
새 테이블 생성
ALTER TABLE MODIFY QUERY.를 사용해 새 테이블을 사용하도록 수정할 수 있습니다. 이 방식을 사용하면 예를 들어 otel_logs_v3처럼 테이블에 버전을 붙일 수 있습니다.
이 방식을 사용하면 사용자가 쿼리해야 하는 테이블이 여러 개가 됩니다. 여러 테이블을 한꺼번에 쿼리하려면 테이블 이름에 와일드카드 패턴을 사용할 수 있는 merge 함수를 사용할 수 있습니다. 아래에서는 otel_logs 테이블의 v2와 v3를 쿼리하는 예를 보여줍니다:
merge 함수를 사용하지 않으면서 여러 테이블을 결합한 테이블을 최종 사용자에게 제공하려면 Merge 테이블 엔진을 사용할 수 있습니다. 아래에서 이를 설명합니다:
EXCHANGE 테이블 구문을 사용해 이를 업데이트할 수 있습니다. 예를 들어 v4 테이블을 추가하려면 새 테이블을 생성한 다음, 이를 이전 버전과 원자적으로 교체할 수 있습니다.