메인 콘텐츠로 건너뛰기
경량 업데이트는 현재 베타입니다. 문제가 발생하면 ClickHouse 리포지토리에 이슈를 등록해 주십시오.
경량 UPDATE SQL 문은 표현식 filter_expr에 일치하는 [db.]table 테이블의 행을 업데이트합니다. 이는 데이터 파트에서 전체 컬럼을 재작성하는 비용이 큰 ALTER TABLE ... UPDATE 쿼리와 구분하기 위해 “경량 업데이트”라고 부릅니다. 이 기능은 MergeTree 테이블 엔진 계열에서만 사용할 수 있습니다.
UPDATE [db.]table [ON CLUSTER cluster] SET column1 = expr1 [, ...] [IN PARTITION partition_expr] WHERE filter_expr;
filter_exprUInt8 유형이어야 합니다. 이 쿼리는 filter_expr의 값이 0이 아닌 행에서, 지정된 컬럼의 값을 해당 표현식에 대응하는 값으로 업데이트합니다. 값은 CAST 연산자를 사용해 컬럼 유형으로 변환됩니다. 프라이머리 키 또는 파티션 키 계산에 사용되는 컬럼은 업데이트할 수 없습니다.

예시

UPDATE hits SET Title = 'Updated Title' WHERE EventDate = today();

UPDATE wikistat SET hits = hits + 1, time = now() WHERE path = 'ClickHouse';

경량 업데이트는 데이터를 즉시 업데이트하지 않습니다

경량 UPDATE는 **패치 파트(patch parts)**를 사용해 구현됩니다. 패치 파트는 업데이트된 컬럼과 행만 포함하는 특별한 유형의 데이터 파트(data part)입니다. 경량 UPDATE는 패치 파트를 생성하지만, 저장소에 있는 원본 데이터를 물리적으로 즉시 수정하지는 않습니다. 업데이트 과정은 INSERT ... SELECT ... 쿼리와 비슷하지만, UPDATE 쿼리는 패치 파트 생성이 완료될 때까지 기다린 뒤에 반환됩니다. 업데이트된 값의 특징은 다음과 같습니다.
  • 패치가 적용되므로 SELECT 쿼리에서 즉시 확인할 수 있습니다
  • 이후 머지 및 뮤테이션 과정에서만 물리적으로 구체화됩니다
  • 모든 활성 파트에 패치가 구체화되면 자동으로 정리됩니다

경량 업데이트 요구 사항

경량 업데이트는 MergeTree, ReplacingMergeTree, CollapsingMergeTree, VersionedCollapsingMergeTree 엔진과 그 ReplicatedShared 버전에서 지원됩니다. 경량 업데이트를 사용하려면 테이블 설정 enable_block_number_columnenable_block_offset_column을 사용하여 _block_number_block_offset 컬럼의 머티리얼라이즈를 활성화해야 합니다.

경량 DELETE

경량 DELETE 쿼리는 ALTER UPDATE mutation 대신 경량 UPDATE로 실행할 수 있습니다. 경량 DELETE의 동작 방식은 lightweight_delete_mode 설정으로 제어됩니다.

성능 고려 사항

경량 업데이트의 장점:
  • 업데이트의 지연 시간은 INSERT ... SELECT ... 쿼리의 지연 시간과 비슷합니다
  • 데이터 파트(data part)의 전체 컬럼이 아니라 업데이트된 컬럼과 값만 기록됩니다
  • 현재 실행 중인 머지/뮤테이션이 완료될 때까지 기다릴 필요가 없으므로 업데이트의 지연 시간을 예측할 수 있습니다
  • 경량 업데이트는 병렬로 실행할 수 있습니다
잠재적인 성능 영향:
  • 패치를 적용해야 하는 SELECT 쿼리에는 오버헤드가 추가됩니다
  • 패치를 적용해야 하는 데이터 파트의 컬럼에는 스키핑 인덱스가 사용되지 않습니다. 테이블에 패치 파트가 있으면 패치를 적용할 필요가 없는 데이터 파트를 포함해 프로젝션도 사용되지 않습니다.
  • 지나치게 빈번한 소규모 업데이트는 “too many parts” 오류를 유발할 수 있습니다. 예를 들어 업데이트할 id를 WHERE 절의 단일 IN 절에 넣는 방식으로 여러 업데이트를 하나의 쿼리로 묶는 것이 좋습니다
  • 경량 업데이트는 소량의 행(테이블의 약 10%까지)을 업데이트하도록 설계되었습니다. 더 많은 양을 업데이트해야 한다면 ALTER TABLE ... UPDATE 뮤테이션을 사용하는 것이 좋습니다

동시 작업

경량 업데이트는 일반적인 뮤테이션과 달리 현재 실행 중인 머지나 뮤테이션이 완료될 때까지 기다리지 않습니다. 동시에 실행되는 경량 업데이트의 일관성은 설정 update_sequential_consistencyupdate_parallel_mode로 제어됩니다.

UPDATE 권한

UPDATE를 사용하려면 ALTER UPDATE 권한이 필요합니다. 특정 사용자가 지정된 테이블에서 UPDATE SQL 문을 실행할 수 있도록 하려면 다음을 실행하세요:
GRANT ALTER UPDATE ON db.table TO username;

구현 세부 사항

패치 파트는 일반 파트와 동일하지만, 업데이트된 컬럼과 몇 가지 시스템 컬럼만 포함합니다.
  • _part - 원본 파트의 이름
  • _part_offset - 원본 파트에서의 행 번호
  • _block_number - 원본 파트에서 해당 행의 block 번호
  • _block_offset - 원본 파트에서 해당 행의 block 오프셋
  • _data_version - 업데이트된 데이터의 데이터 버전(UPDATE 쿼리에 할당된 block 번호)
평균적으로 패치 파트에서는 업데이트된 각 행마다 약 40바이트(비압축 데이터)의 오버헤드가 발생합니다. 시스템 컬럼은 업데이트해야 할 원본 파트의 행을 찾는 데 도움이 됩니다. 시스템 컬럼은 원본 파트의 가상 컬럼과 연관되어 있으며, 패치 파트를 적용해야 할 경우 읽기 시 추가됩니다. 패치 파트는 _part_part_offset을 기준으로 정렬됩니다. 패치 파트는 원본 파트와 서로 다른 파티션에 속합니다. 패치 파트의 파티션 ID는 patch-<hash of column names in patch part>-<original_partition_id>입니다. 따라서 컬럼이 서로 다른 패치 파트는 서로 다른 파티션에 저장됩니다. 예를 들어 세 가지 업데이트 SET x = 1 WHERE <cond>, SET y = 1 WHERE <cond>, SET x = 1, y = 1 WHERE <cond>는 서로 다른 3개의 파티션에 3개의 패치 파트를 생성합니다. 패치 파트는 서로 머지될 수 있으며, 이를 통해 SELECT 쿼리에서 적용해야 하는 패치 수를 줄이고 오버헤드를 낮출 수 있습니다. 패치 파트 머지에는 _data_version을 버전 컬럼으로 사용하는 replacing 머지 알고리즘이 사용됩니다. 따라서 패치 파트에는 각 업데이트된 행에 대한 최신 버전만 항상 저장됩니다. 경량 업데이트는 현재 실행 중인 머지와 뮤테이션이 완료되기를 기다리지 않으며, 항상 데이터 파트의 현재 스냅샷을 사용해 업데이트를 실행하고 패치 파트를 생성합니다. 따라서 패치 파트를 적용하는 경우는 두 가지가 있을 수 있습니다. 예를 들어 파트 A를 읽을 때 패치 파트 X를 적용해야 한다고 가정하겠습니다.
  • X에 파트 A 자체가 포함된 경우. 이는 UPDATE가 실행될 때 A가 머지에 참여하고 있지 않았던 경우에 발생합니다.
  • X에 파트 A에 포함된 BC가 포함된 경우. 이는 UPDATE가 실행될 때 (B, C) -> A 머지가 진행 중이었던 경우에 발생합니다.
이 두 가지 경우에 대해 패치 파트를 적용하는 방식도 각각 두 가지가 있습니다.
  • 정렬된 컬럼 _part, _part_offset을 기준으로 머지를 사용합니다.
  • _block_number, _block_offset 컬럼을 기준으로 join을 사용합니다.
join 모드는 merge 모드보다 느리고 더 많은 메모리가 필요하지만, 사용 빈도는 더 낮습니다.
마지막 수정일 2026년 6월 10일