INSERT ... SELECT クエリに対応しています。deduplicate_insert 設定は、同期挿入と非同期挿入を制御します。INSERT ... SELECT には追加の注意が必要で、専用の設定があります。挿入の重複排除を制御する設定を参照してください。
制限事項
不確実な挿入ステータス
重複排除ウィンドウの上限
*_deduplication_window を超える数の他の挿入操作が行われると、重複排除が意図どおりに機能しない場合があります。この場合、同じデータが複数回挿入される可能性があります。
挿入の重複排除を制御する設定
- 宛先テーブルで重複排除ログが保持されていること。これはテーブルレベルの設定です。
- クエリで重複排除が有効になっていること。これはクエリレベルの設定です。
テーブルレベルの設定
*MergeTree エンジンのみです。
*ReplicatedMergeTree エンジンでは、重複排除ログはデフォルトで有効になっており、replicated_deduplication_window および replicated_deduplication_window_seconds 設定で制御されます。非レプリケートの *MergeTree エンジンでは、ログは non_replicated_deduplication_window 設定で制御され、デフォルト値は 0 です。したがって、通常の MergeTree テーブルでは、そのウィンドウを正の値に設定するまで重複排除は行われません。
上記の設定は、テーブルの重複排除ログのパラメーターを決定します。重複排除ログには有限個の block_id が保存され、これによって重複排除の動作が決まります (以下を参照) 。
replicated_deduplication_window_for_async_inserts および replicated_deduplication_window_seconds_for_async_inserts はレガシー設定です。現在、同期挿入と非同期挿入は 1 つの重複排除ログを共有するため、replicated_deduplication_window が両方を制御します。レガシー設定は古い ClickHouse Keeper ディレクトリの範囲のみを制限しており、これはローリングアップグレード中に重要になります。クエリレベルの設定
deduplicate_insert には次の 3 つの値を指定できます。
enable—INSERTクエリの重複排除を有効にします。disable—INSERTクエリの重複排除を無効にします。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_deduplicateとasync_insert_deduplicateは、deduplicate_insertがbackward_compatible_choiceの場合にのみ読み取られます。
レガシーおよび廃止された設定
バージョン 26.2 では、
async_insert と deduplicate_blocks_in_dependent_materialized_views のデフォルトも有効に変更されました。compatibility 互換性設定は、これら 3 つすべてを制御します。compatibility を 26.2 より前のバージョンに設定すると、これらの設定には以前のデフォルトが適用されます。deduplicate_insert は backward_compatible_choice となり、insert_deduplicate と async_insert_deduplicate に判断を委ねます。明示的に設定した値は常に優先され、compatibility の影響を受けません。
挿入の重複排除の仕組み
*MergeTree エンジンを使用するテーブルでは、各ブロックに一意の block_id が割り当てられます。これは、そのブロック内のデータのハッシュです。この block_id は、挿入操作の一意なキーとして使用されます。同じ block_id が重複排除ログ内で見つかった場合、そのブロックは重複と見なされ、テーブルには挿入されません。
このアプローチは、挿入操作に異なるデータが含まれる場合には有効です。ただし、同じデータを意図的に複数回挿入する場合は、重複排除の処理を制御するために insert_deduplication_token 設定を使用する必要があります。この設定では、各 insert に対して一意のトークンを指定でき、ClickHouse はそれを使用してデータが重複かどうかを判定します。insert_deduplication_token の優先度が高く、トークンが指定されている場合、ClickHouse はデータのハッシュ値を使用しません。
INSERT ... VALUES クエリでは、挿入されるデータのブロックへの分割は決定論的であり、設定によって決まります。したがって、挿入を再試行する際は、初回の操作と同じ設定値を使用する必要があります。
INSERT ... SELECT の重複排除
INSERT ... SELECT クエリでは、SELECT 部分が試行のたびに同じデータを同じ順序で返す必要があります。そうでない場合、ブロックと block_id が異なるため、再試行は重複として認識されません。
ClickHouse はログソースデータが変更されていないことを検証できませんが、クエリ自体が再現可能な結果を生成するかどうかは確認できます。次の両方を満たす場合、SELECT は安定していると見なされます。
- クエリに
ORDER BY ALL句が含まれている。認識されるのはリテラルのORDER BY ALLのみです。通常のORDER BY <expressions>は認識されず、2 つ以上のSELECTをUNIONしたクエリは安定とは見なされません。 - 読み取りパイプラインが単一ストリームで終了する。
insert_deduplication_token は安定性の代替手段として同等です。この場合、データではなくトークンによって insert が識別されます。
設定 deduplicate_insert_select で動作を選択します。
enable_when_possible と enable_even_for_bad_queries は deduplicate_insert の設定も考慮します。これが disable の場合、クエリは重複排除されません。force_enable は deduplicate_insert をオーバーライドします。
選択したテーブルは再試行の間に更新される可能性があることに注意してください。この場合、2 つの方法は逆の動作をします。
insert_deduplication_tokenがない場合、block_idはデータから計算されます。結果が変更されると異なるblock_idが生成され、重複排除は行われません。そのため、再試行では最初の試行で書き込まれたデータに加えて、新しいデータが挿入されます。insert_deduplication_tokenがある場合、トークンだけで insert が識別されます。異なるデータを挿入することになった場合でも、再試行は重複として認識され、破棄されます。
非同期挿入の重複排除
async_insert) では、同期挿入と同様に、再試行時に重複排除が行われます。deduplicate_insert は両方を制御するため、個別の設定は不要です。
この 2 種類の挿入は同じ重複排除ログを共有し、block_id も同じ方法で計算します。そのため、重複排除を損なうことなくクライアントを同期挿入と非同期挿入の間で切り替えられます。また、一方のモードで送信した再試行も、もう一方のモードで送信した試行の重複として認識されます。重複排除に依存するテーブルでも、ワークロードを同期挿入から非同期挿入へ安全に移行できます。
バージョン 26.2 より前では、非同期挿入の重複排除はデフォルトで無効で、
async_insert_deduplicate によって制御されていました。この設定は現在、deduplicate_insert が backward_compatible_choice の場合にのみ読み取られます。重複排除の粒度
- キューに入れられた各クエリは、バッチに1つの重複排除トークンを追加します。
- トークンは、クエリで
insert_deduplication_tokenが指定されている場合はその値、指定されていない場合はそのクエリが追加した行のハッシュです。 - バッチ化はトークンに影響せず、
insert_deduplication_tokenはクエリのバッチへのグループ化方法に影響しません。
- バッチ内の1つのクエリが重複している場合、ClickHouse はそのクエリの行のみを削除します。バッチ内の残りの行は通常どおり挿入されます。パーツ内のすべての行が削除される場合にのみ、そのパーツ全体がスキップされます。
- 同じバッチ内の2つのクエリが同じトークンを持つ場合、2つ目のクエリはパーツが書き込まれる前に破棄されます。これはパーティションごとに適用されます。2つのクエリが異なるパーティションに行を書き込む場合、両方とも保持されます。
system.events の DuplicatedAsyncInserts および SelfDuplicatedAsyncInserts イベントは、これら2つのケースをカウントします。
非同期挿入とmaterialized view
NOT_IMPLEMENTED例外をスローします。
ビューの出力が1つのブロックに収まらない場合、2つ目のブロックが出力されます。max_block_sizeは、1つのブロックに収まる行数を設定します。カラム変換、フィルタリング、集約で行数が増えることはないため、常に1つのブロックに収まります。JOINでは行数が増える場合があります。結果がmax_block_size以下であれば機能しますが、それを超えると失敗します。
複数のブロックを出力するビューを介して挿入するには、deduplicate_blocks_in_dependent_materialized_views = 0を設定するか、同期挿入を使用します。
materialized view における挿入の重複排除
replicated_deduplication_windowreplicated_deduplication_window_secondsnon_replicated_deduplication_window
deduplicate_blocks_in_dependent_materialized_views によっても制御され、バージョン 26.2 以降はデフォルトで有効になっています。両方の設定で許可する必要があります。deduplicate_insert はソーステーブルに挿入されたデータを重複排除し、deduplicate_blocks_in_dependent_materialized_views は依存先テーブル内のデータも追加で重複排除します。完全な重複排除を行う場合は、両方を有効にしてください。
materialized view 配下のテーブルにブロックを挿入する際、ClickHouse はソーステーブルの block_id と追加の識別子を組み合わせた文字列をハッシュ化して block_id を計算します。これにより、materialized view 内で正確な重複排除が保証され、materialized view 配下の宛先テーブルに到達する前にどのような変換が適用されたかにかかわらず、元の挿入に基づいてデータを区別できるようになります。
例
materialized view の変換後に生成される同一ブロック
dst テーブルに挿入されていることがわかります。select からの 2 つのブロック — INSERT 時の 2 つのパーツです。各パーツには異なるデータが含まれています。
mv_dst テーブルに 2 つのパーツが挿入されていることがわかります。これらのパーツには同じデータが含まれていますが、重複排除されていません。
dst テーブルと mv_dst テーブルの両方で有効です。
INSERT時の同一ブロック
dst への挿入用にも 2 つのブロックがあるはずです。しかし実際には、table dst に挿入されたのは 1 つのブロックだけであることがわかります。これは、2 つ目のブロックが重複排除されたためです。このブロックは同じデータを持ち、さらに挿入されたデータからハッシュとして計算される重複排除用の秘密鍵 block_id も同一です。この動作は想定どおりではありません。このようなケースが発生することはまれですが、理論上は起こりえます。このようなケースを正しく処理するには、ユーザーが insert_deduplication_token を指定する必要があります。以下の例でこれを修正してみましょう。
insert_deduplication_token を使用した挿入時の同一ブロック
insert_deduplication_token のほうが優先される点に注意してください。insert_deduplication_token が指定されている場合、ClickHouse はデータのハッシュ値を使用しません。
異なる挿入操作でも、materialized viewの基になるテーブルでは変換後に同じデータが生成される
mv_dst テーブルには毎回同じデータが挿入されます。ソースデータが異なるため、データは重複排除されません。
同等のデータを 1 つの基になるテーブルに挿入する異なる materialized view
mv_dst に挿入されました (予想どおり) 。
dst と mv_dst の両方で重複排除されます。