-
[ClickHouse] Mutation 알아보기Database/Clickhouse 2024. 4. 13. 07:29728x90반응형
- 목차
들어가며.
Mutation 은 테이블의 데이터를 수정하거나 삭제하는 작업을 의미합니다.
이는 ALTER TABLE ... DELETE 또는 ALTER TABLE ... UPDATE 와 같은 명령어로 실행되며, 백그라운드에서 비동기적으로 처리됩니다.
Mutation은 MergeTree 엔진을 사용하는 테이블에서 지원되며, 데이터 파트를 새로운 버전으로 재작성하여 변경사항을 적용합니다.
ClickHouse 의 Mutation 은 일반적인 관계형 데이터베이스 관리 시스템(RDBMS)의 DELETE 및 UPDATE 연산과 유사한 동작으로 생각하시면 됩니다.
하지만 차이점들이 존재합니다.
- Mutation 은 ALTER TABLE 과 같이 DDL 형식으로 실행됩니다.
- MySQL 과 같은 DB 에서 DELETE, UPDATE 등의 쿼리가 동기적으로 실행되는 반면, Mutation 은 백그라운드에서 실행됩니다.
- Mutation 은 WHERE 절에 의해서 지정된 모든 Part 파일들에 대해 적용됩니다. 그래서 상당 수의 Disk IO 가 발생할 수 있습니다.
우선 간단히 위와 같이 정리를 해보았는데요.
이어지는 내용에서 자세한 설명과 예시 및 실습을 진행해보도록 하겠습니다.
Mutation 이란 ?
ClickHouse 에서 Mutation은 테이블의 기존 데이터를 수정하거나 삭제하는 작업을 의미합니다.
ALTER TABLE ... DELETE 또는 ALTER TABLE ... UPDATE 명령어를 통해 수행되며, 이러한 명령어는 테이블의 데이터를 변경하는 데 사용됩니다.
또한 Mutation 명령어의 진행 상황은 system.mutations 시스템 테이블에서 확인할 수 있습니다.
우선 간단한 MergeTree Table 을 생성하고, Mutation 을 수행해보도록 하겠습니다.
아래의 Docker 명령어를 통해서 ClickHouse Container 를 실행합니다.
docker run -d --platform linux/amd64 --name clickhouse clickhouse:24.9.3
docker exec -it clickhouse bash
그리고 아래의 SQL 쿼리들은 Mutation 테스트를 수행할 간단한 예시 쿼리입니다.
user_events 라는 이름의 MergeTree 엔진의 테이블을 생성합니다.
toYYYYMM(event_time) 을 기준으로 PARTITION KEY 를 설정하였구요.
따라서 event_time 의 Month 가 다른 Row 마다 Part 파일이 생성될 겁니다.
CREATE TABLE user_events ( event_id UInt32, event_time DateTime, user_id UInt32, event_type String ) ENGINE = MergeTree() PARTITION BY toYYYYMM(event_time) ORDER BY (user_id, event_time);
INSERT INTO user_events (event_id, event_time, user_id, event_type) VALUES (1, '2024-01-11 10:00:00', 101, 'login'), (2, '2024-02-11 10:05:00', 102, 'purchase'), (3, '2024-03-11 10:10:00', 101, 'logout'), (4, '2024-04-11 10:15:00', 103, 'login'), (5, '2024-05-11 10:20:00', 104, 'purchase');
위의 Table Create DDL 과 Insert DML 이 모두 실행되면, 생성된 Part File 들은 아래와 같이 5개가 생성됩니다.
그 이유는 PARTITION BY 로 설정된 event_time 칼럼이 YYYYMM 을 기준으로 파티셔닝되기 때문입니다.
ls -a1 /var/lib/clickhouse/data/default/user_events/
아래의 Query 는 2024년 01월에 해당하는 모든 Row 들을 삭제하는 쿼리입니다.
ALTER TABLE user_events DELETE WHERE event_time > '2024-01-01 00:00:00' AND event_time <= '2024-01-31 23:59:59';
Mutation 을 실행하기 이전에 system.mutations 의 상태를 조회해보았습니다.
아래 이미지와 같이 현재는 비어있는 상황입니다.
하지만 Delete Mutation 실행 이후에 user_events 의 테이블 상황과 Parts 들의 상태는 아래와 같습니다.
아래의 이미지처럼 event_time 이 2024-01 에 속하는 Row 는 삭제됩니다.
그리고 Parts 들 또한 아래와 같이 변경됩니다.
아래의 이미지와 같이 _6 Suffix 가 붙은 새로운 Part 들이 생성됩니다.
Part 의 Naming Convention 에서 맨 마지막의 숫자는 Data Version 을 의미합니다.
사실 저의 추측은 아래와 같습니다.
저는 Partition Key 로 사용된 event_time 칼럼이 2024-01 인 Row 만을 제거하였습니다.
따라서 202401 에 해당하는 Part 만이 변경되기를 기대하였는데,
실상은 위 이미지와 같이 모든 Part 에 대해서 새로운 Version 의 Part 들이 생성되었습니다.
많은 양의 Part 와 적은 범위의 Mutataion 실험.
Part 들이 매우 많고, 극히 일부의 데이터를 삭제하는 Mutation 을 수행합니다.
아래의 Insert Query 는 1억개의 Row 들을 생성하는 Query 입니다.
INSERT INTO user_events (event_id, event_time, user_id, event_type) SELECT number AS event_id, addSeconds('2024-01-01 00:00:00', rand() % 31536000) AS event_time, rand() % 1000 + 1 AS user_id, ['login', 'purchase', 'logout'][rand() % 3 + 1] AS event_type FROM numbers(100000000);
ALTER TABLE user_events DELETE WHERE event_time > '2024-01-01 00:00:00' AND event_time <= '2024-01-31 23:59:59';
위 쿼리를 실행하면 아래와 같이 많은 양의 Part 들이 생성됩니다.
아래의 이미지는 Delete Mutation 을 실행한 이후의 Part 들의 상태입니다.
_1081 이라는 Suffix 가 붙은 새로운 Part 들이 생성됩니다.
Mutation 의 적용 범위와 무관하게 전역적으로 Mutation 이 수행되는 것으로 관찰됩니다.
( 뭔가 삭제할 파일을 찾는 최적화가 되지 않는 느낌 ? )
아래의 결과는 system.mutations 의 조회 내용입니다.
select database, table, parts_to_do, parts_to_do_names, block_numbers.number, block_numbers.partition_id from system.mutations format vertical;
- database 와 table : Mutation 이 적용되는 범위
- parts_to_do: Mutation 이 수행되는 Part 의 갯수를 의미합니다.
- 위의 케이스에서는 36 개의 Part 가 그 대상이 되며, 새로운 Part 가 만들어집니다.
- parts_to_do_names: 삭제되어야할 Part 와 새롭게 만들어지는 Part 의 이름들입니다.
- 아래의 이미지와 같이 Mutation 의 대상이 되는 Part 들은 _1081 와 같이 Data Version 이 붙은 새로운 Part 들로 만들어집니다.
Update Mutation 알아보기.
이번에는 아래의 Update Mutation 을 통해서 Row 를 업데이트하고, 이에 따른 변경 사항들을 알아보도록 하겠습니다.
ALTER TABLE user_events UPDATE event_type = 'purchase' WHERE user_id = 101;
Update Mutation 수행 후, 아래와 같이 user_id: 101 에 해당하는 Row 의 event_type 값이 변경됩니다.
system.mutations 테이블에서 조회되는 Mutation 기록과 변경된 Part 상태는 아래와 같습니다.
전반적으로 Delete & Update 의 종류와 관계없니 Mutation 는 동일하게 동작하는 것으로 관찰됩니다.
select database, table, parts_to_do, parts_to_do_names, block_numbers.number, block_numbers.partition_id from system.mutations format vertical;
정리하며.
- ClickHouse Mutation 은 비동기적으로 실행됩니다.
- ALTER TABLE ... 와 같은 DDL 방식으로 Mutation 이 수행됩니다.
- 이는 Background 에서 수행되기에 실행 결과를 확인하려면 system.mutations 테이블을 활용해야합니다.
- ClickHouse Mutation 은 많은 양의 Part 파일들을 생성하게 됩니다.
- 실험의 결과 Mutation 의 Where 문장과 Part 의 범위가 최적의 대응이 되지 않습니다.
- 아마도 Background 에서 Optimize Table 과정이 수행되지 않나 추측해봅니다.
- 결론적으로 적은 범위의 Mutation 이더라도 많은 양의 Part 들이 수정되기에 퍼포먼스 이슈를 고려해야합니다.
반응형'Database > Clickhouse' 카테고리의 다른 글
[ClickHouse] min_insert_block_size_rows 설정 알아보기 (0) 2024.06.02 [ClickHouse] Logger 설정하기 (0) 2024.06.02 [ClickHouse] Parts & Partition 알아보기 (0) 2024.02.29 [ClickHouse] primary.idx 파일 알아보기 (0) 2024.02.28 [Clickhouse] ReplicatedMergeTree 알아보기 (0) 2024.02.18