재시도 시 삽입 중복 제거

재시도 시 삽입 중복 제거 (Deduplicating inserts on retries)

삽입 연산은 타임아웃 같은 오류로 실패할 수 있습니다. 삽입이 실패하면 데이터가 성공적으로 삽입되었을 수도, 아닐 수도 있습니다. 이 가이드는 삽입 재시도 시 중복 제거가 어떻게 동작해 같은 데이터가 한 번 이상 삽입되지 않는지 다룹니다.

출처: 문서

본문

삽입 연산은 타임아웃 같은 오류로 가끔 실패할 수 있습니다. 삽입이 실패하면 데이터가 성공적으로 삽입되었을 수도 있고 아닐 수도 있습니다. 이 가이드는 삽입 재시도 시 중복 제거가 어떻게 동작해 같은 데이터가 한 번 이상 삽입되지 않게 하는지 다룹니다.

삽입이 재시도되면 ClickHouse는 데이터가 이미 성공적으로 삽입되었는지 판단하려고 시도합니다. 삽입된 데이터가 중복으로 표시되면 ClickHouse는 그것을 대상 테이블에 삽입하지 않습니다. 그러나 사용자는 데이터가 정상적으로 삽입된 것처럼 여전히 성공 상태를 받습니다.

중복 제거는 동기 삽입, 비동기 삽입, INSERT ... SELECT 쿼리를 모두 다룹니다. 하나의 설정 deduplicate_insert가 동기와 비동기 삽입을 제어합니다. INSERT ... SELECT는 추가 주의가 필요하며 자체 설정이 있습니다. "삽입 중복 제거를 제어하는 설정"을 참고하세요.

제한사항

불확실한 삽입 상태

사용자는 삽입 연산이 성공할 때까지 재시도해야 합니다. 모든 재시도가 실패하면 데이터가 삽입되었는지 아닌지 판단하는 것이 불가능합니다. 머티얼라이즈드 뷰가 관련되면 데이터가 어느 테이블에 나타났는지도 불분명합니다. 머티얼라이즈드 뷰가 소스 테이블과 동기화되지 않을 수 있습니다.

중복 제거 윈도우 한계

재시도 시퀀스 동안 *_deduplication_window보다 많은 다른 삽입 연산이 발생하면 중복 제거가 의도대로 동작하지 않을 수 있습니다. 이 경우 같은 데이터가 여러 번 삽입될 수 있습니다.

삽입 중복 제거를 제어하는 설정

ClickHouse는 다음 두 가지가 모두 성립할 때만 삽입을 중복 제거합니다:

  • 대상 테이블이 중복 제거 로그를 유지합니다. 이것은 테이블 수준 설정입니다.
  • 쿼리에 대해 중복 제거가 활성화되어 있습니다. 이것은 쿼리 수준 설정입니다.

테이블 수준 설정

*MergeTree 엔진만 삽입 시 중복 제거를 지원합니다.

*ReplicatedMergeTree 엔진의 경우 중복 제거 로그가 기본적으로 활성화되어 있으며 replicated_deduplication_windowreplicated_deduplication_window_seconds 설정으로 제어됩니다. 비복제 *MergeTree 엔진의 경우 로그는 non_replicated_deduplication_window 설정으로 제어되는데, 기본값은 0입니다. 따라서 일반 MergeTree 테이블은 그 윈도우를 양수 값으로 설정할 때까지 아무것도 중복 제거하지 않습니다.

위 설정들은 테이블의 중복 제거 로그 매개변수를 결정합니다. 중복 제거 로그는 유한한 수의 block_id를 저장하며, 이것이 중복 제거가 동작하는 방식을 결정합니다(아래 참고).

replicated_deduplication_window_for_async_insertsreplicated_deduplication_window_seconds_for_async_inserts는 레거시 설정입니다. 동기와 비동기 삽입은 이제 하나의 중복 제거 로그를 공유하므로 replicated_deduplication_window가 둘 다를 지배합니다. 레거시 설정은 롤링 업그레이드 중에 중요한 옛 ClickHouse Keeper 디렉터리만 제한합니다.

쿼리 수준 설정

설정 적용 대상 기본값 목적
deduplicate_insert 모든 INSERT, 동기 또는 비동기 enable 삽입 중복 제거의 주요 스위치
deduplicate_insert_select INSERT ... SELECT enable_when_possible SELECT 결과가 재현 가능하지 않을 때 무엇을 할지 결정
insert_deduplication_token 모든 INSERT '' 데이터 대신 사용자 제공 문자열로 삽입을 식별
deduplicate_blocks_in_dependent_materialized_views 머티얼라이즈드 뷰 아래의 테이블 1 중복 제거를 종속 머티얼라이즈드 뷰의 대상으로 확장

deduplicate_insert는 세 값을 받습니다:

  • enableINSERT 쿼리에 중복 제거가 활성화됩니다.
  • disableINSERT 쿼리에 중복 제거가 비활성화됩니다.
  • backward_compatible_choice — 결정이 레거시 설정 insert_deduplicate(동기 삽입)와 async_insert_deduplicate(비동기 삽입)에 위임됩니다.

deduplicate_insert = disable로 실행되는 쿼리는 자신의 블록에 block_id를 쓰지 않는다는 점에 주목하세요. 그런 데이터는 나중에 deduplicate_insert = enable로 재시도해도 중복 제거될 수 없습니다. 대상 테이블이 중복 제거 로그를 유지하지 않을 때도 마찬가지입니다: 기록되는 것이 없으므로 재시도 시 일치시킬 것도 없습니다.

우선순위

  • INSERT ... SELECT 쿼리의 경우 deduplicate_insert_select가 결정합니다. INSERT … SELECT 중복 제거 참고.
  • 그 외 모든 INSERT의 경우 deduplicate_insert가 결정합니다.
  • insert_deduplicateasync_insert_deduplicatededuplicate_insertbackward_compatible_choice일 때만 읽힙니다.

레거시 및 폐기된 설정

설정 상태 대신 사용
insert_deduplicate 레거시. deduplicate_insert = backward_compatible_choice일 때만 읽힘 deduplicate_insert
async_insert_deduplicate 레거시. deduplicate_insert = backward_compatible_choice일 때만 읽힘 deduplicate_insert
insert_select_deduplicate 폐기됨. 효과 없음 deduplicate_insert_select
update_insert_deduplication_token_in_dependent_materialized_views 폐기됨. 효과 없음

버전 26.2부터 deduplicate_insert는 기본값이 enable입니다. 따라서 insert_deduplicate = 0을 설정해도 더 이상 스스로 중복 제거를 끄지 않습니다. 중복 제거를 비활성화하려면 deduplicate_insert = disable을 설정하세요.

버전 26.2는 또한 async_insertdeduplicate_blocks_in_dependent_materialized_views의 기본값을 활성화로 바꿨습니다. compatibility 설정이 세 가지를 모두 지배합니다. compatibility26.2보다 이른 버전으로 설정하면 이 설정들은 예전 기본값을 유지합니다: deduplicate_insertbackward_compatible_choice가 되어 결정을 insert_deduplicateasync_insert_deduplicate에 넘깁니다. 명시적으로 할당한 설정은 항상 존중되며 compatibility의 영향을 받지 않습니다.

삽입 중복 제거가 동작하는 방식

데이터가 ClickHouse에 삽입되면 행 수와 바이트 수에 기반해 데이터를 블록으로 나눕니다.

*MergeTree 엔진을 사용하는 테이블의 경우 각 블록은 그 블록 데이터의 해시인 고유한 block_id를 할당받습니다. 이 block_id는 삽입 연산의 고유 키로 사용됩니다. 중복 제거 로그에서 같은 block_id가 발견되면 그 블록은 중복으로 간주되어 테이블에 삽입되지 않습니다.

이 접근 방식은 삽입이 서로 다른 데이터를 담는 경우 잘 동작합니다. 그러나 같은 데이터를 의도적으로 여러 번 삽입한다면 insert_deduplication_token 설정을 사용해 중복 제거 과정을 제어해야 합니다. 이 설정은 각 삽입에 고유 토큰을 지정할 수 있게 해 주며, ClickHouse는 그것으로 데이터가 중복인지 판단합니다. insert_deduplication_token은 더 높은 우선순위를 가집니다: 토큰이 제공되면 ClickHouse는 데이터의 해시 합을 사용하지 않습니다.

INSERT ... VALUES 쿼리의 경우 삽입된 데이터를 블록으로 나누는 것은 결정적이며 설정에 의해 결정됩니다. 따라서 초기 연산과 같은 설정 값으로 삽입을 재시도해야 합니다.

INSERT ... SELECT 중복 제거

INSERT ... SELECT 쿼리의 경우 SELECT 부분은 매 시도마다 같은 순서로 같은 데이터를 반환해야 합니다. 그렇지 않으면 블록이 달라지고 block_id가 달라지며, 재시도가 중복으로 인식되지 않습니다.

ClickHouse는 소스 데이터가 변하지 않았음을 검증할 수 없지만, 쿼리 자체가 재현 가능한 결과를 만드는지는 확인할 수 있습니다. SELECT는 다음 두 가지가 모두 성립할 때 안정적(stable)으로 취급됩니다:

  • 쿼리가 ORDER BY ALL 절을 담습니다. 리터럴 ORDER BY ALL만 인식됩니다. 일반 ORDER BY <expressions>는 인식되지 않으며, 두 개 이상의 SELECTUNION은 절대 안정적이지 않습니다.
  • 읽기 파이프라인이 단일 스트림으로 끝납니다.

비어 있지 않은 insert_deduplication_token은 안정성의 동등한 대용품입니다. 토큰이 데이터가 아닌 삽입을 식별하기 때문입니다.

deduplicate_insert_select 설정이 무엇을 할지 선택합니다:

동작
enable_when_possible (기본) SELECT가 안정적이거나 토큰이 설정되었을 때 중복 제거. 그렇지 않으면 중복 제거를 건너뛰고 서버 로그에 메시지를 씁니다.
force_enable 항상 중복 제거. SELECT가 안정적이지 않고 토큰도 없으면 DEDUPLICATION_IS_NOT_POSSIBLE 예외를 던집니다.
enable_even_for_bad_queries 안정성에 관계없이 중복 제거. 하위 호환용으로 유지. 불안정한 SELECT에서는 재시도가 보통 중복으로 인식되지 않으므로 다른 값을 선호하세요.
disable INSERT ... SELECT를 절대 중복 제거하지 않습니다.

enable_when_possibleenable_even_for_bad_queriesdeduplicate_insert도 존중합니다: 그것이 disable이면 쿼리는 중복 제거되지 않습니다. force_enablededuplicate_insert를 덮어씁니다.

재시도 사이에 선택된 테이블이 갱신될 수 있음을 명심하세요. 그러면 두 경로가 반대 방식으로 동작합니다:

  • insert_deduplication_token 없이 block_id가 데이터에서 계산됩니다. 변경된 결과는 다른 block_id를 만들고 중복 제거가 발생하지 않으며, 재시도는 첫 시도가 이미 쓴 것 위에 새 데이터를 삽입합니다.
  • insert_deduplication_token을 사용하면 토큰만이 삽입을 식별합니다. 재시도는 중복으로 인식되어 버려집니다. 다른 데이터를 삽입했을 텐데도요.

재시도가 무엇을 의미하길 원하는지에 맞는 경로를 선택하세요. 추가로 대량의 데이터를 삽입하면 블록 수가 중복 제거 로그 윈도우를 넘칠 수 있고, ClickHouse는 블록을 중복 제거할지 알지 못합니다.

비동기 삽입 중복 제거

비동기 삽입(async_insert, 버전 26.2부터 기본 활성화)은 동기 삽입과 같은 방식으로 재시도 시 중복 제거됩니다. deduplicate_insert가 둘 다를 제어하므로 별도 스위치가 필요 없습니다.

두 삽입 타입은 또한 하나의 중복 제거 로그를 공유하고 block_id를 같은 방식으로 계산합니다. 따라서 동기와 비동기 삽입 사이를 전환해도 중복 제거가 깨지지 않으며, 한 모드에서 보낸 재시도는 다른 모드에서 보낸 시도의 중복으로 여전히 인식됩니다. 워크로드를 동기에서 비동기 삽입으로 옮기는 것은 중복 제거에 의존하는 테이블에서 안전합니다.

버전 26.2 이전에는 비동기 삽입의 중복 제거가 기본적으로 비활성화였고 async_insert_deduplicate로 제어되었습니다. 그 설정은 이제 deduplicate_insertbackward_compatible_choice일 때만 읽힙니다.

중복 제거 입자(granularity)

서버는 여러 비동기 삽입을 한 배치로 모아 그 배치를 하나 이상의 파트로 씁니다. 구분된 파티션 키 값마다 최소 하나씩입니다. 중복 제거는 배치 단위가 아니라 사용자 쿼리 단위로 동작합니다:

  • 대기 중인 각 쿼리는 배치에 중복 제거 토큰 하나를 기여합니다.
  • 토큰은 쿼리가 제공할 때의 insert_deduplication_token 값이거나, 그 쿼리가 기여한 행들의 해시입니다.
  • 배칭은 토큰에 영향을 주지 않으며, insert_deduplication_token은 쿼리가 배치로 그룹핑되는 방식에 영향을 주지 않습니다.

이것은 두 가지 결과를 가집니다:

  • 배치의 한 쿼리가 중복이면 ClickHouse는 그 쿼리의 행만 제거합니다. 배치의 나머지는 정상적으로 삽입됩니다. 파트는 그 안의 모든 행이 제거되었을 때만 완전히 건너뜁니다.
  • 같은 배치의 두 쿼리가 같은 토큰을 담으면 두 번째 것은 파트가 쓰여지기 전에 버려집니다. 이것은 파티션별로 적용됩니다: 두 쿼리가 다른 파티션에 행을 쓰면 둘 다 살아남습니다.

system.eventsDuplicatedAsyncInsertsSelfDuplicatedAsyncInserts 이벤트가 이 두 경우를 셉니다.

비동기 삽입과 머티얼라이즈드 뷰

비동기 삽입의 중복 제거는 종속 머티얼라이즈드 뷰와 함께 동작합니다. 규칙은 간단합니다: 블록 하나가 들어오면 블록 하나가 나갑니다. 뷰의 내부 쿼리가 하나의 입력 블록을 하나의 출력 블록으로 만들면 중복 제거가 동작합니다. 뷰가 두 번째 블록을 내보내면 ClickHouse는 NOT_IMPLEMENTED 예외를 던집니다.

뷰의 출력이 한 블록에 맞지 않을 때 뷰는 두 번째 블록을 내보냅니다. max_block_size가 몇 행이 들어맞는지 설정합니다. 컬럼 변환, 필터링, 집계는 결코 행을 추가하지 않으므로 항상 한 블록에 머무릅니다. JOIN은 행을 추가할 수 있습니다. 결과가 max_block_size 아래에 머무르는 동안에는 동작하고, 그 이상이면 실패합니다.

둘 이상의 블록을 내보내는 뷰를 통해 삽입하려면 deduplicate_blocks_in_dependent_materialized_views = 0을 설정하거나 동기 삽입을 사용하세요.

머티얼라이즈드 뷰와 삽입 중복 제거

테이블에 하나 이상의 머티얼라이즈드 뷰가 있으면 삽입된 데이터는 정의된 변환과 함께 그 뷰들의 대상에도 삽입됩니다. 변환된 데이터도 재시도 시 중복 제거됩니다. ClickHouse는 타깃 테이블에 삽입된 데이터를 중복 제거하는 것과 같은 방식으로 머티얼라이즈드 뷰의 중복 제거를 수행합니다.

소스 테이블에 대해 다음 설정을 사용해 이 과정을 제어할 수 있습니다:

머티얼라이즈드 뷰 아래 테이블의 중복 제거는 버전 26.2부터 기본 활성화된 사용자 프로필 설정 deduplicate_blocks_in_dependent_materialized_views에 의해 추가로 지배됩니다. 두 스위치 모두 허용해야 합니다: deduplicate_insert는 소스 테이블에 삽입된 데이터를 중복 제거하고, deduplicate_blocks_in_dependent_materialized_views는 종속 테이블의 데이터를 추가로 중복 제거합니다. 완전한 중복 제거를 원하면 둘 다 활성화하세요.

머티얼라이즈드 뷰 아래 테이블에 블록을 삽입할 때 ClickHouse는 소스 테이블의 block_id와 추가 식별자를 결합한 문자열을 해싱해 block_id를 계산합니다. 이것은 머티얼라이즈드 뷰 내에서 정확한 중복 제거를 보장해, 대상 테이블에 도달하기 전에 적용된 변환과 무관하게 원래 삽입에 기반해 데이터를 구분할 수 있게 합니다.

예제

머티얼라이즈드 뷰 변환 후 동일한 블록

머티얼라이즈드 뷰 내부의 변환 중 생성된 동일한 블록은 서로 다른 삽입 데이터에 기반하므로 중복 제거되지 않습니다.

예제는 다음과 같습니다:

CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000
AS SELECT
    0 AS key,
    value AS value
FROM dst;
SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;

위 설정은 한 행만 담은 일련의 블록으로 테이블에서 선택할 수 있게 합니다. 이 작은 블록들은 뭉개지지 않고 테이블에 삽입될 때까지 그대로 유지됩니다.

기본적으로 활성화되어 있지만 머티얼라이즈드 뷰의 중복 제거를 명시적으로 만듭니다:

SET deduplicate_blocks_in_dependent_materialized_views=1;
INSERT INTO dst SELECT
    number + 1 AS key,
    IF(key = 0, 'A', 'B') AS value
FROM numbers(2);

SELECT
    *,
    _part
FROM dst
ORDER BY all;
┌─key─┬─value─┬─_part─────┐
│   1 │ B     │ all_0_0_0 │
│   2 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘

여기서 dst 테이블에 두 파트가 삽입되었음을 볼 수 있습니다. select에서 2블록 — 삽입 시 2파트. 파트는 서로 다른 데이터를 담습니다.

SELECT
    *,
    _part
FROM mv_dst
ORDER BY all;
┌─key─┬─value─┬─_part─────┐
│   0 │ B     │ all_0_0_0 │
│   0 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘

여기서 mv_dst 테이블에 2개의 파트가 삽입되었음을 볼 수 있습니다. 파트는 같은 데이터를 담지만 중복 제거되지 않습니다.

INSERT INTO dst SELECT
    number + 1 AS key,
    IF(key = 0, 'A', 'B') AS value
FROM numbers(2);

SELECT
    *,
    _part
FROM dst
ORDER BY all;
┌─key─┬─value─┬─_part─────┐
│   1 │ B     │ all_0_0_0 │
│   2 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘
SELECT
    *,
    _part
FROM mv_dst
ORDER by all;
┌─key─┬─value─┬─_part─────┐
│   0 │ B     │ all_0_0_0 │
│   0 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘

여기서 삽입을 재시도하면 모든 데이터가 중복 제거됨을 볼 수 있습니다. dstmv_dst 테이블 모두에서 중복 제거가 동작합니다.

삽입 시 동일한 블록

CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;

삽입:

INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2);

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘

위 설정으로 select에서 두 블록이 결과가 나옵니다 — 결과적으로 dst 테이블에 삽입할 두 블록이 있어야 합니다. 그러나 dst 테이블에 한 블록만 삽입되었음을 볼 수 있습니다. 두 번째 블록이 중복 제거되었기 때문입니다. 삽입된 데이터의 해시로 계산된 중복 제거 키 block_id가 같은 데이터를 가집니다. 이 동작은 기대한 것이 아닙니다. 이런 경우는 드물지만 이론적으로 가능합니다. 이런 경우를 올바르게 처리하려면 사용자가 insert_deduplication_token을 제공해야 합니다. 다음 예제로 이것을 고쳐 봅시다:

insert_deduplication_token으로 동일한 블록 삽입

CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;

삽입:

INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘

두 개의 동일한 블록이 기대대로 삽입되었습니다.

SELECT 'second attempt';

INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘

재시도된 삽입이 기대대로 중복 제거되었습니다.

SELECT 'third attempt';

INSERT INTO dst SELECT
    1 AS key,
    'b' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘

그 삽입도 서로 다른 삽입 데이터를 담고 있음에도 중복 제거되었습니다. insert_deduplication_token이 더 높은 우선순위를 가짐을 주의하세요: insert_deduplication_token이 제공되면 ClickHouse는 데이터의 해시 합을 사용하지 않습니다.

서로 다른 삽입 연산이 머티얼라이즈드 뷰의 기본 테이블에서 변환 후 같은 데이터 생성

CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000
AS SELECT
    0 AS key,
    value AS value
FROM dst;

SET deduplicate_blocks_in_dependent_materialized_views=1;

select 'first attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
└───────────────┴─────┴───────┴───────────┘
select 'second attempt';

INSERT INTO dst VALUES (2, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
│ from dst   │   2 │ A     │ all_1_1_0 │
└────────────┴─────┴───────┴───────────┘
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘

매번 서로 다른 데이터를 삽입합니다. 그러나 mv_dst 테이블에는 같은 데이터가 삽입됩니다. 소스 데이터가 달랐으므로 데이터는 중복 제거되지 않습니다.

동등한 데이터로 하나의 기본 테이블에 삽입하는 서로 다른 머티얼라이즈드 뷰

CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE TABLE mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_first
TO mv_dst
AS SELECT
    0 AS key,
    value AS value
FROM dst;

CREATE MATERIALIZED VIEW mv_second
TO mv_dst
AS SELECT
    0 AS key,
    value AS value
FROM dst;

SET deduplicate_blocks_in_dependent_materialized_views=1;

select 'first attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘

두 개의 동일한 블록이 mv_dst 테이블에 삽입되었습니다(기대대로).

SELECT 'second attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘

그 재시도 연산은 dstmv_dst 두 테이블 모두에서 중복 제거됩니다.

더 알아보기 (Learn more)