CoalescingMergeTree 테이블 엔진

CoalescingMergeTree 테이블 엔진

이 테이블 엔진은 버전 25.6부터 OSS와 Cloud 둘 다에서 사용할 수 있어요. 이 엔진은 MergeTree에서 상속해요. 핵심 차이는 데이터 파트 병합 방식이에요: CoalescingMergeTree 테이블의 경우 ClickHouse는 같은 기본 키(더 정확히는 같은 정렬 키)를 가진 모든 행을, 각 컬럼에 대한 최신 비-NULL 값을 포함하는 단일 행으로 대체해요. 이는 컬럼 레벨 upsert를 가능하게 해요. 즉, 전체 행이 아닌 특정 컬럼만 업데이트할 수 있어요.

CoalescingMergeTree는 키가 아닌 컬럼의 Nullable 타입과 함께 사용하도록 설계됐어요. 컬럼이 Nullable이 아니면 동작은 ReplacingMergeTree와 같아요.

출처: 문서

본문

테이블 생성하기

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE = CoalescingMergeTree([columns])
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

요청 매개변수에 대한 설명은 request description을 참고해요.

CoalescingMergeTree의 매개변수

Columns

columns - 선택. 값이 병합될 컬럼 이름의 튜플. 제공된 컬럼은 파티션이나 정렬 키에 있으면 안 돼요. columns를 지정하지 않으면 ClickHouse는 정렬 키에 없는 모든 컬럼의 값을 병합해요.

쿼리 절

CoalescingMergeTree 테이블을 만들 때 MergeTree 테이블을 만들 때와 같은 절들이 필요해요.

사용 예시

다음 테이블을 고려해요.

CREATE TABLE test_table
(
    key UInt64,
    value_int Nullable(UInt32),
    value_string Nullable(String),
    value_date Nullable(Date)
)
ENGINE = CoalescingMergeTree()
ORDER BY key

데이터를 삽입해요:

INSERT INTO test_table VALUES(1, NULL, NULL, '2025-01-01'), (2, 10, 'test', NULL);
INSERT INTO test_table VALUES(1, 42, 'win', '2025-02-01');
INSERT INTO test_table(key, value_date) VALUES(2, '2025-02-01');

결과는 다음과 같아요.

SELECT * FROM test_table ORDER BY key;
┌─key─┬─value_int─┬─value_string─┬─value_date─┐
│   1 │        42 │ win          │ 2025-02-01 │
│   1 │      ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ         │ 2025-01-01 │
│   2 │      ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ         │ 2025-02-01 │
│   2 │        10 │ test         │       ᴺᵁᴸᴸ │
└─────┴───────────┴──────────────┴────────────┘

올바르고 최종적인 결과를 위한 권장 쿼리:

SELECT * FROM test_table FINAL ORDER BY key;
┌─key─┬─value_int─┬─value_string─┬─value_date─┐
│   1 │        42 │ win          │ 2025-02-01 │
│   2 │        10 │ test         │ 2025-02-01 │
└─────┴───────────┴──────────────┴────────────┘

FINAL 수정자를 사용하면 ClickHouse가 쿼리 시점에 병합 로직을 적용하도록 강제해 각 컬럼에 대해 올바른 병합된 "최신" 값을 보장해요. 이것은 CoalescingMergeTree 테이블에서 조회할 때 가장 안전하고 정확한 방법이에요. GROUP BY를 사용하는 접근 방식은 기본 파트가 완전히 병합되지 않았다면 잘못된 결과를 반환할 수 있어요.

SELECT key, last_value(value_int), last_value(value_string), last_value(value_date)  FROM test_table GROUP BY key; -- Not recommended.

Tuple 요소 집계

allow_tuple_element_aggregation 설정이 활성화되면 Tuple 컬럼이 재귀적으로 평면화되어 각 리프 요소가 독립적으로 병합(coalescing)에 참여해요. 이렇게 하면 단일 Tuple 컬럼에 여러 필드를 저장하고 병합 중 요소별로 병합되게 할 수 있어요 — 각 Nullable 하위 컬럼은 최신 비-NULL 값을 독립적으로 유지해요.

평면화된 하위 컬럼에는 일반 컬럼과 같은 규칙이 적용돼요.

  • 정렬 키나 파티션 키의 Tuple에 속하는 하위 컬럼은 병합에서 제외돼요
  • columns가 지정되면 나열된 Tuple 컬럼의 하위 컬럼만 병합돼요

이 설정은 불변(immutable)이며 테이블 생성 시 지정해야 해요.

CREATE TABLE coalescing_tuples
(
    key UInt64,
    data Tuple(
        value_a Nullable(UInt64),
        value_b Nullable(String),
        nested Tuple(
            value_c Nullable(UInt64)
        )
    )
) ENGINE = CoalescingMergeTree()
ORDER BY key
SETTINGS allow_tuple_element_aggregation = 1;

INSERT INTO coalescing_tuples VALUES (1, (100, NULL, (NULL)));
INSERT INTO coalescing_tuples VALUES (1, (NULL, 'hello', (42)));

SELECT key, data.value_a, data.value_b, data.nested.value_c FROM coalescing_tuples FINAL;
┌─key─┬─data.value_a─┬─data.value_b─┬─data.nested.value_c─┐
│   1 │          100 │ hello        │                  42 │
└─────┴──────────────┴──────────────┴─────────────────────┘

더 알아보기 (Learn more)