이 쿼리는 테이블의 데이터 파트에 대해 예약되지 않은 머지를 시작합니다. 일반적으로 OPTIMIZE TABLE ... FINAL 사용은 권장되지 않습니다(문서 참고). 이 기능은 일상적인 운영이 아니라 관리 용도로 사용하도록 설계되었기 때문입니다.
OPTIMIZE는 Too many parts 오류를 해결할 수 없습니다.
구문
OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL | FORCE] [DEDUPLICATE [BY expression]]
OPTIMIZE TABLE [db.]name DRY RUN PARTS 'part_name1', 'part_name2' [, ...] [DEDUPLICATE [BY expression]] [CLEANUP]
OPTIMIZE 쿼리는 MergeTree 계열(구체화된 뷰(Materialized View) 포함)과 Buffer 엔진에서 지원됩니다. 다른 테이블 엔진은 지원되지 않습니다.
OPTIMIZE를 ReplicatedMergeTree 계열의 테이블 엔진에 사용하면, ClickHouse는 머지를 위한 작업을 생성하고 모든 레플리카에서 실행될 때까지 기다립니다(alter_sync 설정이 2인 경우). 또는 현재 레플리카에서 실행될 때까지 기다립니다(alter_sync 설정이 1인 경우).
- 어떤 이유로든
OPTIMIZE가 머지를 수행하지 않더라도 클라이언트에는 알리지 않습니다. 알림을 활성화하려면 optimize_throw_if_noop 설정을 사용하십시오.
PARTITION을 지정하면 지정한 파티션만 최적화됩니다. 파티션 표현식을 설정하는 방법.
FINAL 또는 FORCE를 지정하면 모든 데이터가 이미 하나의 파트에 있더라도 최적화가 수행됩니다. 이 동작은 optimize_skip_merged_partitions 설정으로 제어할 수 있습니다. 또한 동시 머지가 진행 중이더라도 머지가 강제로 수행됩니다.
DEDUPLICATE를 지정하면 완전히 동일한 행이 중복 제거됩니다(by 절을 지정하지 않은 경우에는 모든 컬럼을 비교함). 이는 MergeTree 엔진에서만 의미가 있습니다.
비활성 레플리카가 OPTIMIZE 쿼리를 실행할 때까지 기다릴 시간(초)은 replication_wait_for_inactive_replica_timeout 설정으로 지정할 수 있습니다.
alter_sync가 2로 설정되어 있고 일부 레플리카가 replication_wait_for_inactive_replica_timeout 설정에 지정된 시간보다 오래 비활성 상태로 남아 있으면, UNFINISHED 예외가 발생합니다.
DRY RUN 절은 지정된 파트의 머지를 시뮬레이션하지만 결과를 커밋하지는 않습니다. 병합된 파트는 임시 위치에 기록된 뒤 검증되고, 이후 폐기됩니다. 원본 파트와 테이블 데이터는 변경되지 않습니다.
다음과 같은 경우에 유용합니다.
- ClickHouse 버전 전반에서 머지의 정확성을 테스트합니다.
- 머지 관련 버그를 재현 가능하게 재현합니다.
- 머지 성능을 벤치마크합니다.
DRY RUN은 MergeTree 계열 테이블에서만 지원됩니다. 파트 이름 목록과 함께 PARTS 키워드를 반드시 지정해야 합니다. 지정된 모든 파트는 존재해야 하고, 활성 상태여야 하며, 동일한 파티션에 속해야 합니다.
DRY RUN은 FINAL 및 PARTITION과 함께 사용할 수 없습니다. DEDUPLICATE(선택적으로 컬럼 지정 가능) 및 CLEANUP(ReplacingMergeTree 테이블용)과는 함께 사용할 수 있습니다.
구문
OPTIMIZE TABLE [db.]name DRY RUN PARTS 'part_name1', 'part_name2' [, ...] [DEDUPLICATE [BY expression]] [CLEANUP]
기본적으로 최종적으로 생성된 병합된 파트는 CHECK TABLE 쿼리와 유사한 방식으로 검증됩니다. 이 동작은 optimize_dry_run_check_part 설정으로 제어되며, 기본적으로 활성화되어 있습니다. 이를 비활성화하면 검증을 건너뛰므로 머지 자체를 벤치마크할 때 유용할 수 있습니다.
예시
CREATE TABLE dry_run_example (key UInt64, value String) ENGINE = MergeTree ORDER BY key;
INSERT INTO dry_run_example VALUES (1, 'a'), (2, 'b');
INSERT INTO dry_run_example VALUES (1, 'c'), (4, 'd');
-- 두 파트를 머지하는 시뮬레이션
OPTIMIZE TABLE dry_run_example DRY RUN PARTS 'all_1_1_0', 'all_2_2_0';
-- 중복 제거를 포함한 머지 시뮬레이션
OPTIMIZE TABLE dry_run_example DRY RUN PARTS 'all_1_1_0', 'all_2_2_0' DEDUPLICATE;
-- DRY RUN 이후 파트와 데이터는 변경되지 않음
SELECT name, rows FROM system.parts
WHERE database = currentDatabase() AND table = 'dry_run_example' AND active
ORDER BY name;
┌─name────────┬─rows─┐
│ all_1_1_0 │ 2 │
│ all_2_2_0 │ 2 │
└─────────────┴──────┘
모든 컬럼이 아닌 특정 컬럼 집합에 대해 중복 제거를 수행하려면 컬럼 목록을 명시적으로 지정하거나 *, COLUMNS, EXCEPT 표현식을 조합해 사용할 수 있습니다. 명시적으로 작성했거나 암시적으로 확장된 컬럼 목록에는 행 정렬 표현식(프라이머리 키와 정렬 키 모두)과 파티셔닝 표현식(파티셔닝 키)에 지정된 모든 컬럼이 포함되어야 합니다.
*는 SELECT에서와 마찬가지로 동작합니다. 즉, MATERIALIZED 및 ALIAS 컬럼은 확장에 사용되지 않습니다.또한 빈 컬럼 목록을 지정하거나, 그 결과 빈 컬럼 목록이 되는 표현식을 작성하거나, ALIAS 컬럼을 기준으로 중복 제거를 수행하면 오류가 발생합니다.
구문
OPTIMIZE TABLE table DEDUPLICATE; -- 모든 컬럼
OPTIMIZE TABLE table DEDUPLICATE BY *; -- MATERIALIZED 및 ALIAS 컬럼 제외
OPTIMIZE TABLE table DEDUPLICATE BY colX,colY,colZ;
OPTIMIZE TABLE table DEDUPLICATE BY * EXCEPT colX;
OPTIMIZE TABLE table DEDUPLICATE BY * EXCEPT (colX, colY);
OPTIMIZE TABLE table DEDUPLICATE BY COLUMNS('column-matched-by-regex');
OPTIMIZE TABLE table DEDUPLICATE BY COLUMNS('column-matched-by-regex') EXCEPT colX;
OPTIMIZE TABLE table DEDUPLICATE BY COLUMNS('column-matched-by-regex') EXCEPT (colX, colY);
예시
다음 테이블을 가정해 보겠습니다:
CREATE TABLE example (
primary_key Int32,
secondary_key Int32,
value UInt32,
partition_key UInt32,
materialized_value UInt32 MATERIALIZED 12345,
aliased_value UInt32 ALIAS 2,
PRIMARY KEY primary_key
) ENGINE=MergeTree
PARTITION BY partition_key
ORDER BY (primary_key, secondary_key);
INSERT INTO example (primary_key, secondary_key, value, partition_key)
VALUES (0, 0, 0, 0), (0, 0, 0, 0), (1, 1, 2, 2), (1, 1, 2, 3), (1, 1, 3, 3);
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
│ 1 │ 1 │ 3 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘
다음의 모든 예시는 행이 5개인 이 상태를 기준으로 실행됩니다.
중복 제거에 사용할 컬럼을 지정하지 않으면 모든 컬럼을 기준으로 합니다. 모든 컬럼의 값이 이전 행의 해당 값과 모두 같을 때만 그 행이 제거됩니다.
OPTIMIZE TABLE example FINAL DEDUPLICATE;
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
│ 1 │ 1 │ 3 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘
컬럼을 명시하지 않으면 ALIAS 또는 MATERIALIZED가 아닌 모든 컬럼을 기준으로 테이블에서 중복이 제거됩니다. 위의 테이블에서는 primary_key, secondary_key, value, partition_key 컬럼이 이에 해당합니다:
OPTIMIZE TABLE example FINAL DEDUPLICATE BY *;
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
│ 1 │ 1 │ 3 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘
ALIAS 또는 MATERIALIZED가 아니며, value도 명시적으로 제외한 모든 컬럼(primary_key, secondary_key, partition_key)을 기준으로 중복을 제거합니다.
OPTIMIZE TABLE example FINAL DEDUPLICATE BY * EXCEPT value;
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘
DEDUPLICATE BY <list of columns>
primary_key, secondary_key, partition_key 컬럼을 기준으로 중복을 명시적으로 제거합니다:
OPTIMIZE TABLE example FINAL DEDUPLICATE BY primary_key, secondary_key, partition_key;
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘
DEDUPLICATE BY COLUMNS(<regex>)
정규식과 일치하는 모든 컬럼을 기준으로 중복을 제거합니다. 예를 들면 primary_key, secondary_key, partition_key 컬럼이 있습니다:
OPTIMIZE TABLE example FINAL DEDUPLICATE BY COLUMNS('.*_key');
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 0 │ 0 │ 0 │ 0 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 2 │
└─────────────┴───────────────┴───────┴───────────────┘
┌─primary_key─┬─secondary_key─┬─value─┬─partition_key─┐
│ 1 │ 1 │ 2 │ 3 │
└─────────────┴───────────────┴───────┴───────────────┘