DELETE FROM
DELETE FROM
가벼운(lightweight) DELETE 문은 [db.]table 테이블에서 표현식 expr과 일치하는 행을 제거해요. *MergeTree 테이블 엔진 계열에서만 사용할 수 있습니다.
출처: 문서
본문
DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr1 [, partition_expr2 ...]] WHERE expr;
이것은 무거운(heavyweight) 프로세스인 ALTER TABLE … DELETE 명령과 대비하기 위해 "lightweight DELETE"라고 불러요.
IN PARTITION 절은 삭제를 나열된 파티션으로 제한해요. 이것이 없으면 ReplicatedMergeTree 계열 테이블에서 optimize_mutations_with_partition_pruning 설정(기본값)이 활성화되어 있을 때, ClickHouse가 expr 안의 파티션 키 조건을 자동으로 감지하여 영향을 받는 파티션에서만 삭제합니다. 비복제 MergeTree 테이블에서는 삭제를 특정 파티션으로 제한하려고 명시적인 IN PARTITION 절을 사용하세요.
Examples
-- Deletes all rows from the `hits` table where the `Title` column contains the text `hello`
DELETE FROM hits WHERE Title LIKE '%hello%';
Lightweight DELETE does not delete data immediately
Lightweight DELETE는 mutation으로 구현되며, 행을 삭제된 것으로 표시하지만 즉시 물리적으로 삭제하지는 않아요.
기본적으로 DELETE 문은 행을 삭제된 것으로 표시하는 작업이 완료될 때까지 기다렸다가 반환합니다. 데이터 양이 많으면 오래 걸릴 수 있어요. 또는 설정 lightweight_deletes_sync로 백그라운드에서 비동기적으로 실행할 수도 있습니다. 비활성화하면 DELETE 문은 즉시 반환되지만, 백그라운드 mutation이 끝날 때까지 데이터가 쿼리에 계속 보일 수 있어요.
mutation은 삭제된 것으로 표시된 행을 물리적으로 삭제하지 않으며, 이것은 다음 병합(merge) 중에만 일어납니다. 그 결과 지정되지 않은 기간 동안 데이터가 저장소에서 실제로 삭제되지 않고 삭제된 것으로만 표시될 수 있어요.
데이터가 예측 가능한 시간에 저장소에서 삭제되는 것을 보장해야 한다면 테이블 설정 min_age_to_force_merge_seconds를 고려하세요. 또는 ALTER TABLE … DELETE 명령을 사용할 수 있어요. ALTER TABLE ... DELETE로 데이터를 삭제하면 영향을 받는 모든 파트를 다시 만들기 때문에 상당한 리소스를 소비할 수 있다는 점에 유의하세요.
Deleting large amounts of data
큰 삭제는 ClickHouse 성능에 부정적인 영향을 줄 수 있어요. 테이블의 모든 행을 삭제하려 한다면 TRUNCATE TABLE 명령을 고려하세요.
빈번한 삭제가 예상된다면 custom partitioning key를 사용하는 것을 고려하세요. 그런 다음 ALTER TABLE ... DROP PARTITION 명령으로 해당 파티션과 연관된 모든 행을 빠르게 버릴 수 있어요.
Limitations of lightweight DELETE
Lightweight DELETEs with projections
기본적으로 DELETE는 프로젝션이 있는 테이블에서 동작하지 않아요. 프로젝션의 행이 DELETE 작업에 의해 영향을 받을 수 있기 때문입니다. 하지만 동작을 바꾸는 MergeTree 설정lightweight_mutation_projection_mode가 있습니다.
Performance considerations when using lightweight DELETE
lightweight DELETE 문으로 많은 양의 데이터를 삭제하면 SELECT 쿼리 성능에 부정적인 영향을 줄 수 있어요.
다음도 lightweight DELETE 성능에 부정적인 영향을 줄 수 있어요.
DELETE쿼리의 무거운WHERE조건.- mutations 큐가 다른 많은 mutation으로 차 있으면, 테이블의 모든 mutation이 순차적으로 실행되므로 성능 문제로 이어질 수 있어요.
- 영향을 받는 테이블이 매우 많은 수의 데이터 파트를 가짐.
- compact 파트에 많은 데이터가 있음. Compact 파트에서는 모든 컬럼이 하나의 파일에 저장됩니다.
Delete permissions
DELETE는 ALTER DELETE 권한이 필요해요. 주어진 사용자에 대해 특정 테이블에서 DELETE 문을 활성화하려면 다음 명령을 실행하세요.
GRANT ALTER DELETE ON db.table to username;
How lightweight DELETEs work internally in ClickHouse
-
영향을 받는 행에 "mask"를 적용한다
DELETE FROM table ...쿼리가 실행되면 ClickHouse는 각 행을 "existing" 또는 "deleted"로 표시하는 마스크를 저장합니다. "deleted" 행은 이후 쿼리에서 생략됩니다. 그러나 행은 실제로는 이후 병합에 의해 제거됩니다. 이 마스크를 쓰는 것은ALTER TABLE ... DELETE쿼리가 하는 것보다 훨씬 가볍습니다. 마스크는 보이는 모든 행에True를, 삭제된 행에False를 저장하는 숨겨진_row_exists시스템 컬럼으로 구현됩니다. 이 컬럼은 파트의 일부 행이 삭제된 경우에만 그 파트에 존재합니다. 파트의 모든 값이True일 때는 이 컬럼이 존재하지 않습니다. -
SELECT쿼리가 마스크를 포함하도록 변환된다 마스킹된 컬럼이 쿼리에 사용되면SELECT ... FROM table WHERE condition쿼리는 내부적으로_row_exists에 대한 술어로 확장되어 다음으로 변환됩니다:SELECT ... FROM table PREWHERE _row_exists WHERE condition실행 시점에_row_exists컬럼이 읽혀 어떤 행을 반환하지 말아야 하는지 결정됩니다. 삭제된 행이 많으면 ClickHouse는 나머지 컬럼을 읽을 때 완전히 건너뛸 수 있는 그래뉼(granule)을 결정할 수 있어요. -
DELETE쿼리가ALTER TABLE ... UPDATE쿼리로 변환된다DELETE FROM table WHERE condition은ALTER TABLE table UPDATE _row_exists = 0 WHERE conditionmutation으로 변환됩니다. 내부적으로 이 mutation은 두 단계로 실행됩니다:
각 개별 파트에 대해 SELECT count() FROM table WHERE condition 명령이 실행되어 파트가 영향을 받는지 결정합니다.
위 명령에 기반해 영향을 받는 파트는 변형되고, 영향을 받지 않는 파트에는 하드링크가 만들어집니다. wide 파트의 경우 각 행의 _row_exists 컬럼이 업데이트되고 다른 모든 컬럼의 파일은 하드링크됩니다. compact 파트의 경우 모든 컬럼이 하나의 파일에 함께 저장되므로 모두 다시 작성됩니다.
위 단계에서 볼 수 있듯이, 마스킹 기법을 사용하는 lightweight DELETE는 영향을 받는 파트의 모든 컬럼 파일을 다시 쓰지 않으므로 기존의 ALTER TABLE ... DELETE보다 성능이 좋습니다.