경량 삭제

경량 삭제 (Lightweight delete)

경량 DELETE 문은 표현식 expr과 일치하는 [db.]table의 행을 제거합니다. *MergeTree 테이블 엔진 패밀리에서만 사용할 수 있어요.

출처: 문서

본문

경량 DELETE 문은 표현식 expr과 일치하는 [db.]table 테이블의 행을 제거합니다. *MergeTree 테이블 엔진 패밀리에서만 사용할 수 있습니다.

DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;

무거운 프로세스인 ALTER TABLE … DELETE 명령과 대비하기 위해 "경량 DELETE"라고 부릅니다.

예제

-- Deletes all rows from the `hits` table where the `Title` column contains the text `hello`
DELETE FROM hits WHERE Title LIKE '%hello%';

경량 DELETE는 데이터를 즉시 삭제하지 않음

경량 DELETE는 행을 삭제로 표시하지만 즉시 물리적으로 삭제하지는 않는 뮤테이션으로 구현됩니다.

기본적으로 DELETE 문은 행을 삭제로 표시하는 작업이 완료될 때까지 기다렸다가 반환합니다. 데이터 양이 많으면 오래 걸릴 수 있습니다. 또는 lightweight_deletes_sync 설정을 사용해 백그라운드에서 비동기로 실행할 수 있습니다. 비활성화하면 DELETE 문은 즉시 반환하지만, 백그라운드 뮤테이션이 끝날 때까지 데이터가 쿼리에 여전히 보일 수 있습니다.

뮤테이션은 삭제로 표시된 행을 물리적으로 삭제하지 않습니다. 이것은 다음 병합 중에만 일어납니다. 그 결과, 특정하지 않은 기간 동안 데이터가 스토리지에서 실제로 삭제되지 않고 삭제로 표시만 될 수 있습니다.

데이터가 예측 가능한 시간 안에 스토리지에서 삭제됨을 보장해야 한다면 테이블 설정 min_age_to_force_merge_seconds를 고려하세요. 또는 ALTER TABLE … DELETE 명령을 사용할 수 있습니다. ALTER TABLE ... DELETE로 데이터를 삭제하면 영향을 받는 모든 파트를 재생성하므로 상당한 리소스를 소비할 수 있음에 주의하세요.

대량 데이터 삭제

대량 삭제는 ClickHouse 성능에 부정적 영향을 줄 수 있습니다. 테이블의 모든 행을 삭제하려 한다면 TRUNCATE TABLE 명령을 고려하세요.

잦은 삭제를 예상한다면 커스텀 파티셔닝 키 사용을 고려하세요. 그러면 ALTER TABLE ... DROP PARTITION 명령으로 해당 파티션과 연관된 모든 행을 빠르게 삭제할 수 있습니다.

경량 DELETE의 제한사항

프로젝션과 경량 DELETE

기본적으로 DELETE는 프로젝션이 있는 테이블에서 동작하지 않습니다. 프로젝션의 행이 DELETE 연산의 영향을 받을 수 있기 때문입니다. 그러나 동작을 바꾸는 MergeTree 설정 lightweight_mutation_projection_mode가 있습니다.

경량 DELETE 사용 시 성능 고려사항

경량 DELETE 문으로 대량의 데이터를 삭제하면 SELECT 쿼리 성능에 부정적 영향을 줄 수 있습니다.

다음도 경량 DELETE 성능에 부정적 영향을 줄 수 있습니다:

  • DELETE 쿼리의 무거운 WHERE 조건.
  • 뮤테이션 큐가 다른 뮤테이션으로 가득 차면, 테이블의 모든 뮤테이션이 순차 실행되므로 성능 문제로 이어질 수 있습니다.
  • 영향을 받는 테이블의 데이터 파트 수가 아주 많은 경우.
  • 컴팩트 파트에 데이터가 많은 경우. Compact 파트에서는 모든 컬럼이 하나의 파일에 저장됩니다.

삭제 권한

DELETE에는 ALTER DELETE 권한이 필요합니다. 특정 테이블에서 특정 사용자에게 DELETE 문을 활성화하려면 다음 명령을 실행하세요:

GRANT ALTER DELETE ON db.table to username;

ClickHouse 내부에서 경량 DELETE가 동작하는 방식

  • 영향을 받는 행에 "마스크(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 conditionALTER TABLE table UPDATE _row_exists = 0 WHERE condition 뮤테이션으로 번역됩니다. 내부적으로 이 뮤테이션은 두 단계로 실행됩니다:
    • 각 개별 파트에 대해 파트가 영향을 받는지 결정하기 위해 SELECT count() FROM table WHERE condition 명령이 실행됩니다.
    • 위 명령에 기반해 영향을 받는 파트가 뮤테이션되고, 영향을 받지 않는 파트에는 하드링크가 만들어집니다. wide 파트의 경우 각 행의 _row_exists 컬럼이 갱신되고 다른 모든 컬럼 파일은 하드링크됩니다. 컴팩트 파트의 경우 모든 컬럼이 한 파일에 함께 저장되므로 모두 다시 쓰여집니다.

위 단계에서 우리는 마스킹 기법을 사용하는 경량 DELETE가 영향을 받는 파트의 모든 컬럼 파일을 다시 쓰지 않기 때문에 전통적인 ALTER TABLE ... DELETE보다 성능을 개선함을 알 수 있습니다.

관련 콘텐츠

더 알아보기 (Learn more)