制限事項
不確実な挿入ステータス
重複排除ウィンドウの上限
*_deduplication_window を超える数の他の挿入操作が行われると、重複排除が意図どおりに機能しない場合があります。この場合、同じデータが複数回挿入される可能性があります。
再試行時の挿入の重複排除を有効にする
テーブルの挿入の重複排除
*MergeTree エンジンのみです。
*ReplicatedMergeTree エンジンでは、挿入の重複排除はデフォルトで有効になっており、replicated_deduplication_window および replicated_deduplication_window_seconds 設定で制御されます。非レプリケートの *MergeTree エンジンでは、挿入の重複排除は non_replicated_deduplication_window 設定で制御されます。
上記の設定は、テーブルの重複排除ログのパラメーターを決定します。重複排除ログには有限個の block_id が保存され、これによって重複排除の動作が決まります (以下を参照) 。
クエリレベルの挿入の重複排除
insert_deduplicate=1 を使用すると、クエリレベルの重複排除が有効になります。insert_deduplicate=0 でデータを挿入した場合、その後 insert_deduplicate=1 で挿入を再試行しても、そのデータは重複排除されない点に注意してください。これは、insert_deduplicate=0 での挿入時には、各ブロックに対する block_id が書き込まれないためです。
挿入の重複排除の仕組み
*MergeTree エンジンを使用するテーブルでは、各ブロックに一意の block_id が割り当てられます。これは、そのブロック内のデータのハッシュです。この block_id は、insert 操作の一意なキーとして使用されます。同じ block_id が重複排除ログ内で見つかった場合、そのブロックは重複と見なされ、テーブルには挿入されません。
このアプローチは、挿入操作に異なるデータが含まれる場合には有効です。ただし、同じデータを意図的に複数回挿入する場合は、重複排除の処理を制御するために insert_deduplication_token 設定を使用する必要があります。この設定では、各 insert に対して一意のトークンを指定でき、ClickHouse はそれを使用してデータが重複かどうかを判定します。
INSERT ... VALUES クエリでは、挿入されるデータのブロックへの分割は決定論的であり、設定によって決まります。したがって、挿入を再試行する際は、初回の操作と同じ設定値を使用する必要があります。
INSERT ... SELECT クエリでは、クエリの SELECT 部分が、各操作で同じ順序の同じデータを返すことが重要です。なお、これは実際には実現が困難です。再試行時にデータの順序を安定させるには、クエリの SELECT 部分で ORDER BY ALL 句を定義してください。現時点では、クエリで正確に ORDER BY ALL を使用する必要があります。ORDER BY のサポートはまだ実装されておらず、クエリの SELECT 部分は安定しているとは見なされません。また、再試行の間に選択元のテーブルが更新される可能性がある点にも注意してください。その場合、結果データが変わってしまい、重複排除は行われません。さらに、大量のデータを挿入する場合、挿入後のブロック数が重複排除ログのウィンドウを超過する可能性があり、その場合 ClickHouse はブロックを重複排除すべきか判断できません。
現時点では、INSERT ... SELECT の動作は insert_select_deduplicate 設定によって制御されます。この設定は、INSERT ... SELECT クエリで挿入されたデータに重複排除を適用するかどうかを決定します。詳細と使用例については、リンク先のドキュメントを参照してください。
materialized view における挿入の重複排除
replicated_deduplication_windowreplicated_deduplication_window_secondsnon_replicated_deduplication_window
deduplicate_blocks_in_dependent_materialized_views も有効にする必要があります。
設定 insert_deduplicate=1 を有効にすると、挿入されたデータはソーステーブルで重複排除されます。設定 deduplicate_blocks_in_dependent_materialized_views=1 を有効にすると、依存先テーブルでの重複排除も追加で有効になります。完全な重複排除を行うには、両方を有効にする必要があります。
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 はデータのハッシュ値を使用しません。
異なるinsert操作でも、materialized viewの基になるテーブルでは変換後に同じデータが生成される
mv_dst テーブルには毎回同じデータが挿入されます。ソースデータが異なるため、データは重複排除されません。
同等のデータを 1 つの基になるテーブルに挿入する異なる materialized view
mv_dst に挿入されました (予想どおり) 。
dst と mv_dst の両方で重複排除されます。