경량 업데이트는 현재 베타입니다.
문제가 발생하면 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 mutation 대신 경량 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- 원본 파트의 이름_part_offset- 원본 파트에서의 행 번호_block_number- 원본 파트에서 해당 행의 block 번호_block_offset- 원본 파트에서 해당 행의 block 오프셋_data_version- 업데이트된 데이터의 데이터 버전(UPDATE쿼리에 할당된 block 번호)
_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에 포함된B와C가 포함된 경우. 이는UPDATE가 실행될 때 (B,C) ->A머지가 진행 중이었던 경우에 발생합니다.
- 정렬된 컬럼
_part,_part_offset을 기준으로 머지를 사용합니다. _block_number,_block_offset컬럼을 기준으로 join을 사용합니다.
ALTER UPDATE- 부하가 큰UPDATE작업- Lightweight
DELETE- 경량DELETE작업 APPLY PATCHES- 패치를 데이터 파트에 물리적으로 머티리얼라이즈하도록 강제하는 mutation 작업