PRIMARY KEY ではなく、テーブル定義の ORDER BY セクション) を持つ重複エントリを削除する点で、MergeTreeと異なります。
データの重複排除が行われるのは、マージ時のみです。マージはバックグラウンドでいつ行われるか分からないため、それを前提に計画することはできません。データの一部が未処理のまま残る可能性があります。OPTIMIZE クエリを使って臨時にマージを実行することはできますが、OPTIMIZE クエリでは大量のデータの読み書きが発生するため、これに頼るべきではありません。
したがって、ReplacingMergeTree は容量を節約するためにバックグラウンドで重複データを除去する用途には適していますが、重複が存在しないことを保証するものではありません。
ベストプラクティスやパフォーマンスの最適化方法を含む ReplacingMergeTree の詳細なガイドは、こちらで確認できます。
テーブルの作成
行の一意性は、
PRIMARY KEY ではなく、テーブルの ORDER BY セクションによって決まります。ReplacingMergeTree パラメータ
ver
ver — バージョン番号を表すカラムです。型は UInt*、Date、DateTime、DateTime64 のいずれかです。省略可能なパラメータです。
マージ時、ReplacingMergeTree は同じソートキーを持つすべての行の中から 1 行だけを残します。
verが設定されていない場合は、選択対象内の最後の行が残ります。選択対象とは、マージに参加する一連のパーツに含まれる行の集合です。最も後に作成されたパーツ (最後の insert) が選択対象の最後になります。したがって、重複排除後は、各一意のソートキーについて、直近の insert で追加された最後の行が残ります。verが指定されている場合は、最大のバージョンを持つ行が残ります。複数の行でverが同じ場合は、それらには “verが設定されていない場合” のルールが適用されます。つまり、最も新しく挿入された行が残ります。
is_deleted
is_deleted — マージ時に、この行のデータが state を表すのか、削除対象なのかを判定するために使用されるカラム名です。1 は “deleted” 行、0 は “state” 行です。
カラムのデータ型 — UInt8。
is_deleted は、ver を使用している場合にのみ有効にできます。データに対してどのような操作を行う場合でも、バージョンは増やす必要があります。挿入された 2 つの行のバージョン番号が同じ場合は、最後に挿入された行が保持されます。デフォルトでは、ClickHouse は、その行が削除行であっても、あるキーに対する最後の行を保持します。これは、今後それより低いバージョンの行が
安全に挿入されても、その削除行が引き続き適用されるようにするためです。そのような削除行を永続的に削除するには、テーブル設定 allow_experimental_replacing_merge_with_cleanup を有効にし、次のいずれかを行います。-
テーブル設定
enable_replacing_merge_with_cleanup_for_min_age_to_force_merge、min_age_to_force_merge_on_partition_only、min_age_to_force_merge_secondsを設定します。パーティション内のすべてのパーツがmin_age_to_force_merge_secondsより古い場合、ClickHouse はそれらを すべて 1 つのパーツにマージし、削除行を取り除きます。 -
OPTIMIZE TABLE table [PARTITION partition | PARTITION ID 'partition_id'] FINAL CLEANUPを手動で実行します。
クエリ句
ReplacingMergeTree テーブルの作成時には、MergeTree テーブルの作成時と同じ 句 が必要です。
クエリ時の重複排除 & FINAL
ORDER BY カラムの値を一意の識別子として、最も大きいバージョンだけを保持します。ただし、これで保証されるのはあくまで結果整合性のみであり、行が確実に重複排除されるわけではないため、これに依存すべきではありません。そのため、更新行や削除行もクエリ時に考慮されることで、クエリ結果が不正確になる可能性があります。
正しい結果を得るには、バックグラウンドマージに加えて、クエリ時の重複排除と削除行の除去を行う必要があります。これは FINAL 演算子を使って実現できます。たとえば、次の例を見てみましょう。
FINAL を使用せずにクエリすると、件数が正しくなりません (実際の結果はマージの状況によって異なります) :
FINAL の詳細や、そのパフォーマンスを最適化する方法については、ReplacingMergeTree の詳細ガイドを参照することをお勧めします。