再試行時の挿入の重複排除
挿入操作は、タイムアウトなどのエラーにより失敗することがあります。挿入が失敗した場合、データが正常に挿入されたのかどうかは不明です。このガイドでは、同じデータが二重に挿入されないように、挿入の再試行時に重複排除を有効にする方法を説明します。
挿入が再試行されると、ClickHouseはデータがすでに正常に挿入されたかどうかを判断しようとします。挿入されたデータが重複とマークされると、ClickHouseはそれを宛先テーブルに挿入しません。ただし、ユーザーにはデータが通常通り挿入されたかのように成功操作ステータスが返されます。
再試行時の挿入重複排除を有効にする
テーブルの挿入重複排除
*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
が書き込まれないためです。
挿入重複排除の仕組み
データがClickHouseに挿入されると、データは行数とバイト数に基づいてブロックに分割されます。
*MergeTree
エンジンを使用しているテーブルでは、各ブロックにユニークなblock_id
が割り当てられます。これはそのブロック内のデータのハッシュです。このblock_id
は挿入操作のユニークキーとして使用されます。重複排除ログに同じblock_id
が見つかると、そのブロックは重複と見なされ、テーブルには挿入されません。
このアプローチは、挿入が異なるデータを含む場合によく機能します。しかし、意図的に同じデータが複数回挿入される場合は、重複排除プロセスを制御するためにinsert_deduplication_token
設定を使用する必要があります。この設定により、各挿入のためにユニークなトークンを指定でき、ClickHouseはそれを使用してデータが重複であるかどうかを判断します。
INSERT ... VALUES
クエリに対して、挿入されたデータをブロックに分割することは決定論的であり、設定によって決定されます。したがって、ユーザーは最初の操作と同じ設定値で挿入を再試行する必要があります。
INSERT ... SELECT
クエリの場合、クエリのSELECT
部分が各操作で同じデータを同じ順序で返すことが重要です。実際の使用では、これは達成が困難です。再試行時に安定したデータ順序を確保するために、クエリのSELECT
部分で正確なORDER BY
セクションを定義してください。再試行の間に選択されたテーブルが更新される可能性があるため、結果データが変わり、重複排除が行われない可能性があります。さらに、大量のデータを挿入している場合、挿入後のブロック数が重複排除ログウィンドウをオーバーフローする可能性があり、ClickHouseはブロックを重複排除することができません。
物化ビューを用いた挿入重複排除
テーブルに1つ以上の物化ビューがある場合、挿入されたデータは、定義された変換に従ってそれらのビューの宛先にも挿入されます。変換されたデータも再試行時に重複排除されます。ClickHouseは、物化ビューに挿入されたデータを重複排除するのと同じ方法で、ターゲットテーブルに挿入されたデータの重複排除を行います。
このプロセスは次の設定を使用して、ソーステーブルで制御できます:
replicated_deduplication_window
replicated_deduplication_window_seconds
non_replicated_deduplication_window
ユーザープロファイル設定deduplicate_blocks_in_dependent_materialized_views
を使用することもできます。
物化ビューの下にあるテーブルにブロックを挿入する際、ClickHouseはblock_id
を計算するために、ソーステーブルのblock_id
と追加の識別子を組み合わせた文字列をハッシュ化します。これにより、物化ビュー内での正確な重複排除が保証され、元の挿入に基づいてデータを区別できるようになります。変換が宛先テーブルに到達する前に適用された場合でも同様です。
例
物化ビュー変換後の同一ブロック
物化ビュー内での変換中に生成された同一ブロックは、異なる挿入データに基づいているため、重複排除されません。
以下は例です:
上記の設定により、行を1つだけ含む一連のブロックを持つテーブルから選択できるようになります。これらの小さなブロックは圧縮されず、テーブルに挿入されるまで同じままです。
物化ビューでの重複排除を有効にする必要があります:
ここでは、dst
テーブルに2つのパーツが挿入されたことがわかります。選択からの2ブロック -- 挿入の2パーツ。パーツには異なるデータが含まれています。
ここでは、mv_dst
テーブルに2つのパーツが挿入されたことがわかります。それらのパーツには同じデータが含まれていますが、重複排除は行われません。
ここでは、挿入を再試行すると、すべてのデータが重複排除されることがわかります。重複排除はdst
およびmv_dst
テーブルの両方で機能します。
挿入時の同一ブロック
挿入:
上記の設定により、選択から2つのブロックが得られます。その結果、dst
テーブルに挿入されるべき2つのブロックがあるはずですが、実際には1つのブロックだけが挿入されていることがわかります。これは、2つ目のブロックが重複排除されたためです。データが同じであり、重複排除のためのキーblock_id
が挿入データから計算されたハッシュであるためです。この動作は想定外のものであり、稀に発生することですが理論上可能です。このようなケースを適切に処理するために、ユーザーはinsert_deduplication_token
を提供する必要があります。次の例でそれを修正しましょう。
insert_deduplication_token
を用いた挿入時の同一ブロック
挿入:
期待通りに2つの同一ブロックが挿入されました。
再試行された挿入は期待通りに重複排除されています。
この挿入も、異なる挿入データを含んでいても重複排除されています。insert_deduplication_token
は優先度が高いことに注意してください:ClickHouseはinsert_deduplication_token
が提供されているとき、データのハッシュ合計を使用しません。
物化ビューの基となるテーブルでの変換後に異なる挿入操作が同一データを生成する
毎回異なるデータを挿入しています。しかし、同じデータがmv_dst
テーブルに挿入されています。ソースデータが異なっていたため、データは重複排除されません。
同一の基底テーブルに異なる物化ビューが同じデータを挿入する
mv_dst
テーブルに2つの等しいブロックが挿入されました(期待通り)。
その再試行操作は、dst
およびmv_dst
の両方のテーブルで重複排除されます。