OPTIMIZE TABLE

OPTIMIZE TABLE

이 쿼리는 테이블의 데이터 파트에 대해 예약되지 않은 병합을 초기화하려고 시도합니다. 일반적으로 OPTIMIZE TABLE ... FINAL 사용은 권장하지 않습니다(이 docs 참고). 그 사용 사례는 일상 운영이 아닌 관리용으로 의도된 것이기 때문입니다.

OPTIMIZEToo many parts 오류를 고칠 수 없습니다.

Syntax

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 views 포함)과 Buffer 엔진에 대해 지원됩니다. 다른 테이블 엔진은 지원되지 않습니다.

OPTIMIZEReplicatedMergeTree 계열 테이블 엔진과 함께 사용되면, ClickHouse는 병합을 위한 태스크를 만들고 모든 복제본(alter_sync 설정이 2로 설정된 경우) 또는 활성 복제본(3으로 설정된 경우) 또는 현재 복제본(1로 설정된 경우)에서 실행을 기다립니다.

  • OPTIMIZE가 어떤 이유로든 병합을 수행하지 않으면 클라이언트에 알리지 않습니다. 알림을 활성화하려면 optimize_throw_if_noop 설정을 사용하세요.
  • PARTITION을 지정하면 지정된 파티션만 최적화됩니다. How to set partition expression.
  • FINAL 또는 FORCE를 지정하면 모든 데이터가 이미 하나의 파트에 있어도 최적화가 수행됩니다. 이 동작은 optimize_skip_merged_partitions로 제어할 수 있습니다. 또한 동시 병합이 수행되더라도 병합이 강제됩니다.
  • DEDUPLICATE를 지정하면 완전히 동일한 행(by-clause가 지정되지 않은 경우)이 중복 제거됩니다(모든 컬럼 비교), MergeTree 엔진에서만 의미가 있습니다.

비활성 복제본이 OPTIMIZE 쿼리를 실행할 때까지 기다릴 시간(초)을 replication_wait_for_inactive_replica_timeout 설정으로 지정할 수 있습니다.

alter_sync2로 설정되고 일부 복제본이 replication_wait_for_inactive_replica_timeout 설정이 지정한 시간보다 오래 비활성이면 UNFINISHED 예외가 발생합니다. alter_sync = 3이면 비활성 복제본을 기다리지 않으므로 예외가 발생하지 않습니다.

DRY RUN

DRY RUN 절은 결과를 커밋하지 않고 지정된 파트의 병합을 시뮬레이션합니다. 병합된 파트는 임시 위치에 기록되고, 검증된 다음 폐기됩니다. 원래 파트와 테이블 데이터는 변경되지 않습니다.

이는 다음에 유용합니다:

  • ClickHouse 버전 간 병합 정확성 테스트.
  • 병합 관련 버그를 결정적으로 재현.
  • 병합 성능 벤치마킹.

DRY RUNMergeTree 계열 테이블에서만 지원됩니다. 파트 이름 목록이 있는 PARTS 키워드가 필요합니다. 지정된 모든 파트는 존재하고, 활성이어야 하며, 같은 파티션에 속해야 합니다.

DRY RUNFINALPARTITION과 호환되지 않습니다. DEDUPLICATE(선택적 컬럼 지정 포함) 및 CLEANUP(ReplacingMergeTree 테이블용)과는 결합할 수 있습니다.

Syntax

OPTIMIZE TABLE [db.]name DRY RUN PARTS 'part_name1', 'part_name2' [, ...] [DEDUPLICATE [BY expression]] [CLEANUP]

기본적으로 결과 병합 파트는 CHECK TABLE 쿼리와 유사한 방식으로 검증됩니다. 이 동작은 optimize_dry_run_check_part 설정으로 제어됩니다(기본적으로 활성화). 비활성화하면 검증을 건너뛰며, 병합 자체를 벤치마킹하는 데 유용할 수 있습니다.

Example

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');

-- Simulate merging using two parts
OPTIMIZE TABLE dry_run_example DRY RUN PARTS 'all_1_1_0', 'all_2_2_0';

-- Simulate merging with deduplication
OPTIMIZE TABLE dry_run_example DRY RUN PARTS 'all_1_1_0', 'all_2_2_0' DEDUPLICATE;

-- Parts and data remain unchanged after 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 │
└─────────────┴──────┘

BY expression

모든 컬럼이 아니라 사용자 지정 컬럼 집합에서 중복 제거를 수행하려면 컬럼 목록을 명시적으로 지정하거나 *, COLUMNS, EXCEPT 표현식의 어떤 조합이라도 사용할 수 있습니다. 명시적으로 작성되거나 암시적으로 확장된 컬럼 목록은 행 정렬 표현식(기본 키와 정렬 키 모두)과 파티셔닝 표현식(파티셔닝 키)에 지정된 모든 컬럼을 포함해야 합니다.

*SELECT에서처럼 동작함을 주의하세요: MATERIALIZEDALIAS 컬럼은 확장에 사용되지 않습니다.

또한 빈 컬럼 목록을 지정하거나, 빈 컬럼 목록이 되는 표현식을 작성하거나, ALIAS 컬럼으로 중복 제거하는 것은 오류입니다.

Syntax

OPTIMIZE TABLE table DEDUPLICATE; -- all columns
OPTIMIZE TABLE table DEDUPLICATE BY *; -- excludes MATERIALIZED and ALIAS columns
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);

Examples

다음 테이블을 고려해 보세요:

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);
SELECT * FROM example;

┌─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개 행을 가진 이 상태에 대해 실행됩니다.

DEDUPLICATE

중복 제거를 위한 컬럼이 지정되지 않으면 모두 고려됩니다. 모든 컬럼의 모든 값이 이전 행의 해당 값과 모두 같을 때만 행이 제거됩니다:

OPTIMIZE TABLE example FINAL DEDUPLICATE;
SELECT * FROM example;
┌─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 │
└─────────────┴───────────────┴───────┴───────────────┘

DEDUPLICATE BY *

컬럼이 암시적으로 지정되면, 테이블은 ALIAS 또는 MATERIALIZED가 아닌 모든 컬럼으로 중복 제거됩니다. 위 테이블을 고려하면 primary_key, secondary_key, value, partition_key 컬럼입니다:

OPTIMIZE TABLE example FINAL DEDUPLICATE BY *;
SELECT * FROM example;
┌─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 │
└─────────────┴───────────────┴───────┴───────────────┘

DEDUPLICATE BY * EXCEPT

ALIAS 또는 MATERIALIZED가 아니고 명시적으로 value가 아닌 모든 컬럼으로 중복 제거: primary_key, secondary_key, partition_key 컬럼.

OPTIMIZE TABLE example FINAL DEDUPLICATE BY * EXCEPT value;
SELECT * FROM example;
┌─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;
SELECT * FROM example;
┌─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');
SELECT * FROM example;
┌─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 │
└─────────────┴───────────────┴───────┴───────────────┘

더 알아보기 (Learn more)