경량 업데이트는 현재 베타입니다.
문제가 발생하면 ClickHouse 리포지토리에 이슈를 등록해 주십시오.
UPDATE SQL 문은 표현식 filter_expr에 일치하는 [db.]table 테이블의 행을 업데이트합니다.
이는 데이터 파트에서 전체 컬럼을 재작성하는 비용이 큰 ALTER TABLE ... UPDATE 쿼리와 구분하기 위해 “경량 업데이트”라고 부릅니다.
이 기능은 MergeTree 테이블 엔진 계열에서만 사용할 수 있습니다.
filter_expr는 UInt8 유형이어야 합니다. 이 쿼리는 filter_expr의 값이 0이 아닌 행에서, 지정된 컬럼의 값을 해당 표현식에 대응하는 값으로 업데이트합니다.
값은 CAST 연산자를 사용해 컬럼 유형으로 변환됩니다. 프라이머리 키 또는 파티션 키 계산에 사용되는 컬럼은 업데이트할 수 없습니다.
예시
경량 업데이트는 데이터를 즉시 업데이트하지 않습니다
UPDATE는 **패치 파트(patch parts)**를 사용해 구현됩니다. 패치 파트는 업데이트된 컬럼과 행만 포함하는 특별한 유형의 데이터 파트(data part)입니다.
경량 UPDATE는 패치 파트를 생성하지만, 저장소에 있는 원본 데이터를 물리적으로 즉시 수정하지는 않습니다.
업데이트 과정은 INSERT ... SELECT ... 쿼리와 비슷하지만, UPDATE 쿼리는 패치 파트 생성이 완료될 때까지 기다린 뒤에 반환됩니다.
업데이트된 값의 특징은 다음과 같습니다.
- 패치가 적용되므로
SELECT쿼리에서 즉시 확인할 수 있습니다 - 이후 머지 및 뮤테이션 과정에서만 물리적으로 구체화됩니다
- 모든 활성 파트에 패치가 구체화되면 자동으로 정리됩니다
경량 업데이트 요구 사항
MergeTree, ReplacingMergeTree, CollapsingMergeTree, VersionedCollapsingMergeTree 엔진과 그 Replicated 및 Shared 버전에서 지원됩니다.
경량 업데이트를 사용하려면 테이블 설정 enable_block_number_column 및 enable_block_offset_column을 사용해 _block_number 및 _block_offset 컬럼의 머티리얼라이즈를 활성화해야 합니다.
경량 DELETE
DELETE 쿼리는 ALTER UPDATE 뮤테이션 대신 경량 UPDATE로 실행할 수 있습니다. 경량 DELETE의 동작 방식은 lightweight_delete_mode 설정으로 제어됩니다.
성능 고려 사항
- 업데이트의 지연 시간은
INSERT ... SELECT ...쿼리의 지연 시간과 비슷합니다 - 데이터 파트(data part)의 전체 컬럼이 아니라 업데이트된 컬럼과 값만 기록됩니다
- 현재 실행 중인 머지/뮤테이션이 완료될 때까지 기다릴 필요가 없으므로 업데이트의 지연 시간을 예측할 수 있습니다
- 경량 업데이트는 병렬로 실행할 수 있습니다
- 패치를 적용해야 하는
SELECT쿼리에는 오버헤드가 추가됩니다 - 패치를 적용해야 하는 데이터 파트의 컬럼에는 스키핑 인덱스가 사용되지 않습니다. 테이블에 패치 파트가 있으면 패치를 적용할 필요가 없는 데이터 파트를 포함해 프로젝션도 사용되지 않습니다.
- 지나치게 빈번한 소규모 업데이트는 “too many parts” 오류를 유발할 수 있습니다. 예를 들어 업데이트할 id를
WHERE절의 단일IN절에 넣는 방식으로 여러 업데이트를 하나의 쿼리로 묶는 것이 좋습니다 - 경량 업데이트는 소량의 행(테이블의 약 10%까지)을 업데이트하도록 설계되었습니다. 더 많은 양을 업데이트해야 한다면
ALTER TABLE ... UPDATE뮤테이션을 사용하는 것이 좋습니다
동시 작업
update_sequential_consistency 및 update_parallel_mode로 제어됩니다.
UPDATE 권한
UPDATE를 사용하려면 ALTER UPDATE 권한이 필요합니다. 특정 사용자가 지정된 테이블에서 UPDATE SQL 문을 실행할 수 있도록 하려면 다음을 실행하세요:
구현 세부 사항
_part- 원본 파트의 이름_block_number- 원본 파트에서 해당 행의 block 번호_block_offset- 원본 파트에서 해당 행의 block 오프셋_data_version- 업데이트된 데이터의 데이터 버전(UPDATE쿼리에 할당된 block 번호)
_block_number 및 _block_offset 컬럼이 추가됩니다.
업데이트된 행당 스토리지 오버헤드는 정렬 키 컬럼 값의 크기에 따라 달라집니다.
패치 파트는 원본 파트와 서로 다른 파티션에 속합니다.
패치 파트의 파티션 ID는 patch-<hash of the patch part structure>-<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 머지 알고리즘이 사용됩니다.
따라서 패치 파트에는 각 업데이트된 행에 대한 최신 버전만 항상 저장됩니다.
패치 파트는 테이블의 정렬 키를 기준으로 데이터 파트와 머지하여 적용됩니다. 데이터 파트와 패치 파트에서 정렬 키 컬럼 및 _block_number, _block_offset 컬럼의 값이 같으면 해당 행이 업데이트됩니다.
쿼리에서 정렬 키 컬럼을 선택하지 않더라도 패치 파트를 적용하려면 데이터 파트의 정렬 키 컬럼을 읽어야 합니다.
패치 파트 적용 시 메모리 사용량은 정렬 키 값이 같은 행의 가장 큰 범위로 제한됩니다.
혼합 버전 클러스터에서의 패치 파트 포맷
patch_parts_version으로 제어됩니다.
ClickHouse 26.8 이전 버전은 레거시 v1 포맷만 지원하며, 앞서 설명한 현재 v2 포맷의 패치 파트는 읽을 수 없습니다.
이러한 버전에서 롤링 업그레이드를 수행할 때는 모든 레플리카의 업그레이드가 완료될 때까지 v1 포맷으로 계속 기록해야 합니다. 경량 업데이트를 사용하는 테이블에는 patch_parts_version = 'v1'을 설정하거나, compatibility 설정을 업그레이드 대상 이전 버전으로 지정하십시오.
업그레이드가 완료되면 재정의를 제거하여 v2 포맷으로 패치 파트를 기록하기 시작하십시오.
설정 값과 관계없이 두 포맷의 패치 파트는 모두 읽고 적용할 수 있습니다.
ALTER UPDATE- 부하가 큰UPDATE작업- Lightweight
DELETE- 경량DELETE작업 APPLY PATCHES- 패치를 데이터 파트에 물리적으로 머티리얼라이즈하도록 강제하는 mutation 작업