メインコンテンツまでスキップ
メインコンテンツまでスキップ

再試行時の挿入の重複排除

挿入操作は、タイムアウトなどのエラーにより失敗することがあります。挿入が失敗した場合、データが正常に挿入されたのかどうかは不明です。このガイドでは、同じデータが二重に挿入されないように、挿入の再試行時に重複排除を有効にする方法を説明します。

挿入が再試行されると、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は、物化ビューに挿入されたデータを重複排除するのと同じ方法で、ターゲットテーブルに挿入されたデータの重複排除を行います。

このプロセスは次の設定を使用して、ソーステーブルで制御できます:

ユーザープロファイル設定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の両方のテーブルで重複排除されます。