ClickHouse Korea Collateral
ClickHouse Korea Collateral
/
ClickHouse Upsert 메커니즘의 발전 과정
ClickHouse Upsert 메커니즘의 발전 과정

ClickHouse Upsert 메커니즘의 발전 과정

ClickHouse 분류
Core Architecture
Type
Research
작성자

Ken

ClickHouse는 대용량 분석(OLAP) 환경에 최적화된 컬럼형 데이터베이스로, 전통적인 UPDATE/DELETE 연산을 바로 지원하지 않고, 다양한 엔진과 내부 Mutation 메커니즘을 통해 Upsert(삽입 또는 수정) 기능을 진화시켜 왔습니다. 본 문서에서는 ClickHouse Upsert 메커니즘의 발전 과정을 연대기적으로 정리하고, 각 방식의 내부 원리, 장단점, 그리고 실전에서의 선택 기준을 ClickHouse 공식 문서 및 최신 릴리스 정보를 바탕으로 상세히 설명합니다.

1. ReplacingMergeTree: 중복행 대체 기반 Upsert (초기 ~ 2016)

원리 및 동작 방식

ReplacingMergeTree 엔진은 동일한 키(ORDER BY 기준)를 가진 중복 행 중 하나만 남기고 나머지를 제거하는 방식으로 Upsert 효과를 냅니다. 사용자는 여러 번 INSERT를 통해 같은 키의 데이터를 삽입할 수 있으며, 백그라운드에서 파티션 병합(merge)이 일어날 때 가장 마지막에 삽입된 행(혹은 지정된 버전 컬럼의 최대값 행)만 남깁니다. 병합 시점은 비동기적으로 결정되며, 필요 시 OPTIMIZE ... FINAL 명령으로 강제 병합도 가능합니다[1][2][3].

CREATE TABLE example
(
    id UInt64,
    value String,
    version UInt32
) ENGINE = ReplacingMergeTree(version)
ORDER BY id;

장단점

  • 장점: INSERT만으로 실질적인 UPDATE 효과를 얻을 수 있고, 쓰기 성능이 매우 뛰어남.
  • 단점: 병합 이전까지는 중복 데이터가 남아있어 SELECT 시 FINAL을 사용해야 일관된 최신 데이터를 조회할 수 있음. 병합 시점이 불확실하여 실시간 일관성 요구에는 부적합[1][3][4].

2. CollapsingMergeTree & VersionedCollapsingMergeTree: 1/-1 플래그 및 버전 기반 상태 갱신 (2016~2018)

CollapsingMergeTree

CollapsingMergeTree는 Sign(Int8) 컬럼을 사용하여, 동일 키에 대해 Sign=1(상태)과 Sign=-1(취소) 행이 쌍을 이루면 병합 시 두 행을 모두 제거(collapse)합니다. 이 방식은 이벤트 소싱이나 논리적 삭제/업데이트에 적합하며, INSERT만으로 상태 변경 이력을 관리할 수 있습니다[5][6].

CREATE TABLE collapsing_example
(
    id UInt64,
    value String,
    Sign Int8
) ENGINE = CollapsingMergeTree(Sign)
ORDER BY id;
  • 단점: 입력 순서에 민감하여 +1과 -1이 순차적으로 들어와야 정상 동작. 순서가 어긋나거나 누락되면 데이터 불일치 발생[6].

VersionedCollapsingMergeTree

2018년 v18.14에서 도입된 VersionedCollapsingMergeTree는 Sign과 Version 컬럼을 함께 사용해, 입력 순서와 무관하게 버전별로 쌍을 맞춰 안전하게 collapse합니다. 다중 쓰레드 환경, 비동기 파이프라인 등에서도 데이터 정합성을 보장합니다[4].

CREATE TABLE versioned_collapsing_example
(
    id UInt64,
    value String,
    Sign Int8,
    version UInt32
) ENGINE = VersionedCollapsingMergeTree(Sign, version)
ORDER BY (id, version);
  • 특징: Collapsing 대비 입력 순서 제약이 없고, 버전별로 안전하게 상태 갱신 가능. 단, +1/-1 행 관리를 애플리케이션에서 직접 해야 하며, SELECT 시 FINAL 필요[4].

3. Mutation 기반 ALTER UPDATE/DELETE: 직접 컬럼 수정 (2018~)

2018년 v18.12부터 ClickHouse는 MergeTree 계열 테이블에서 ALTER TABLE ... UPDATE/DELETE 문법을 지원하기 시작했습니다. 이 기능은 Mutation(데이터 변형)으로 구현되며, 조건에 맞는 행을 찾아 컬럼 값을 수정하거나 삭제 표시합니다. 실제로는 기존 데이터 파트를 읽어 새 파트를 생성하는 방식이며, 비동기로 처리됩니다[7].

ALTER TABLE example UPDATE value = 'new_value' WHERE id = 1;
ALTER TABLE example DELETE WHERE id = 2;
  • 장점: 표준 SQL UPDATE/DELETE 문법 사용, 병합 없이도 최신 데이터 즉시 조회 가능.
  • 단점: 컬럼 스토어 특성상 영향을 받는 열 파일 전체를 다시 써야 하므로, 데이터량이 많을수록 성능 부담이 큼. 작은 단위의 잦은 업데이트에는 비효율적임[7].

4. Lightweight Delete / Update: 경량 삭제 및 실시간 반영 (2022~2023)

Lightweight Delete

2022년 v22.8에서 도입된 Lightweight Delete는 DELETE FROM ... 구문을 통해 해당 조건의 행을 즉시 논리적으로 숨깁니다. 실제로는 _row_exists 컬럼에 마스크를 기록하고, 물리 삭제는 차후 병합(merge) 시에만 일어납니다[8].

DELETE FROM example WHERE id = 1;
  • 특징: DELETE 실행 직후부터 해당 행이 조회 결과에 나타나지 않음. 물리적 삭제는 지연되므로, 대량 삭제 시 SELECT 성능에 일시적 영향 가능[8].

Lightweight Update (On-the-fly Mutation)

2023년경 실험적으로 도입된 on-the-fly mutation 기능은 UPDATE 결과를 즉시 SELECT에 반영합니다. UPDATE 명령 실행 후 Mutation이 백그라운드에서 완료되기 전이라도, SELECT 시 변경된 값을 즉시 보여줍니다. 실제 디스크 반영은 기존 Mutation과 동일하게 나중에 처리됩니다.

  • 장점: UPDATE 후 즉시 일치하는 값 조회 가능.
  • 제한: 서브쿼리, 비결정적 함수 등 일부 UPDATE에는 제한이 있고, SELECT 성능 저하 가능성[8].

5. 패치 파트(Patch Parts) 기반 UPDATE: 컬럼형 DB에 최적화된 고속 업데이트 (2025~)

2025년 v25.7 릴리스에서 패치 파트(patch part) 기반 UPDATE가 도입되어, 표준 SQL UPDATE 문법으로 실시간 경량 업데이트가 가능해졌습니다. UPDATE 실행 시, 변경 대상 열의 새로운 값만 별도 패치 파트에 저장하고, SELECT 시 즉시 반영됩니다. 이후 백그라운드 병합 시 원본 파트와 패치 파트가 합쳐지며, 최종적으로 데이터가 일관되게 정리됩니다[9][attachment,ClickHouse Upsert 기능의 연대기 및 엔진별 메커니즘.pdf].

  • 장점: 변경된 컬럼만 기록하므로 I/O 부담이 적고, UPDATE 결과를 바로 조회 가능. 작은 단위의 잦은 업데이트에도 효율적.
  • 단점: 패치 파트가 많아지면 SELECT 성능 저하 및 파트 수 증가 가능. 전체 데이터의 10% 이하 부분 업데이트에 적합하며, 대규모 수정은 기존 Mutation 권장.

6. Upsert 방식별 비교 및 선택 가이드

비교 요약

엔진/기능
주요 특징
장점
단점
ReplacingMergeTree
병합 시 동일 키 중 마지막 행만 유지
INSERT만으로 업데이트 효과, 고속 쓰기
병합 전까지 중복 데이터 잔존, 즉각 일관성 부족(FINAL 필요)
CollapsingMergeTree
Sign(+1/-1) 쌍 병합 시 상쇄
INSERT로 삭제/업데이트 표현, 저장공간 절약
입력 순서 요구, 불완전 쌍 처리 어려움
VersionedCollapsingMergeTree
Sign+Version, 버전별 쌍 병합
순서 무관 안전 갱신
+1/-1 이중 INSERT 필요, SELECT 시 FINAL 필요
ALTER Mutation
조건부 컬럼 수정/삭제
표준 SQL 사용, 최신값 즉시 조회
전체 컬럼 재기록, 대량/빈번 업데이트 시 부하
Lightweight Delete
_row_exists 마스크로 즉시 숨김
빠른 삭제, 대부분 컬럼 재기록 불필요
merge 전까지 공간 차지, SELECT 성능 영향 가능
On-the-fly Update
즉시 SELECT 반영
UPDATE 후 지연 없는 일관성
백그라운드 I/O는 여전, 복잡한 UPDATE 제한
Patch Parts UPDATE
패치 파트에 변경분만 기록
컬럼 단위 고속 업데이트, SQL UPDATE 지원
패치 많으면 SELECT/파트 수 영향, 대량 수정 부적합

선택 기준 및 실전 가이드

  • 실시간 일관성, 표준 SQL UPDATE 필요: 패치 파트 기반 UPDATE, on-the-fly mutation 활용.
  • 대량 데이터, 변경 빈도 낮음: ReplacingMergeTree, CollapsingMergeTree 등 삽입 기반 엔진 활용.
  • 상태 이력 관리, 이벤트 소싱: Collapsing/VersionedCollapsing 계열 추천.
  • 자주 부분 업데이트, 빠른 반영: Patch parts UPDATE.
  • 대규모 일괄 수정/삭제: 기존 ALTER UPDATE/DELETE(Mutation) 활용.

최신 패치 파트 기반 UPDATE의 도입으로 ClickHouse는 OLAP DB임에도 실시간 Upsert에 가까운 경험을 제공하며, 사용자는 워크로드 특성에 맞는 엔진 및 메커니즘을 선택해 최적의 성능과 편의성을 얻을 수 있습니다[attachment,ClickHouse Upsert 기능의 연대기 및 엔진별 메커니즘.pdf][1][5][9][10].

참고 문서 및 공식 자료

  • ReplacingMergeTree | ClickHouse Docs
  • CollapsingMergeTree | ClickHouse Docs
  • VersionedCollapsingMergeTree | ClickHouse Docs
  • ALTER TABLE ... UPDATE Statements | ClickHouse Docs
  • Lightweight Delete | ClickHouse Docs
  • 2025 Changelog | ClickHouse Docs
  • How to Upsert Rows into ClickHouse

ClickHouse Upsert 메커니즘은 계속해서 진화 중이며, 최신 릴리스 및 공식 문서를 참고해 워크로드에 맞는 최적의 방식을 선택하는 것이 중요합니다.