論理削除
軽量の DELETE
ステートメントは、式 expr
に一致する行をテーブル [db.]table
から削除します。これは *MergeTree テーブルエンジンファミリー にのみ利用可能です。
これは、ALTER TABLE ... DELETE コマンドと対比させるために「軽量の DELETE
」と呼ばれています。ALTER TABLE ... DELETE コマンドは重いプロセスです。
例
軽量の DELETE
はデータを即座に削除しない
軽量の DELETE
は、行を削除済みとしてマークするが、それらを即座に物理的に削除しない ミューテーション として実装されています。
デフォルトでは、DELETE
ステートメントは、行を削除済みとしてマークする処理が完了するまで待機してから返されます。データ量が大きい場合、これには長い時間がかかることがあります。代わりに、設定 lightweight_deletes_sync
を使用してバックグラウンドで非同期に実行できます。無効にすると、DELETE
ステートメントは即座に返されますが、バックグラウンドのミューテーションが完了するまでデータはまだクエリに対して表示される可能性があります。
ミューテーションは、削除済みとしてマークされた行を物理的に削除しません。これは次のマージの際にのみ発生します。その結果として、特定の期間、データがストレージから実際には削除されず、削除済みとしてマークされたままになる可能性があります。
ストレージからデータが予測可能な時間内に削除されることを保証する必要がある場合は、テーブル設定 min_age_to_force_merge_seconds
の使用を検討してください。また、ALTER TABLE ... DELETE コマンドを使用することもできます。ただし、ALTER TABLE ... DELETE
を使用してデータを削除すると、影響を受けるすべてのパーツを再作成するため、リソースを大量に消費することがあります。
大量のデータを削除することについて
大量の削除は ClickHouse のパフォーマンスに悪影響を与える可能性があります。テーブルからすべての行を削除しようとする場合は、TRUNCATE TABLE
コマンドの使用を検討してください。
頻繁に削除を行うことが予想される場合は、カスタムパーティショニングキー を使用することを検討してください。その後、ALTER TABLE ... DROP PARTITION
コマンドを使用して、そのパーティションに関連付けられたすべての行を迅速に削除できます。
軽量の DELETE
の制限
プロジェクションを持つ軽量の DELETE
デフォルトでは、DELETE
はプロジェクションを持つテーブルでは機能しません。これは、プロジェクション内の行が DELETE
操作の影響を受ける可能性があるためです。しかし、動作を変更するための MergeTree 設定 lightweight_mutation_projection_mode
があります。
軽量の DELETE
使用時のパフォーマンス考慮事項
軽量の DELETE
ステートメントで大量のデータを削除すると、SELECT クエリのパフォーマンスに悪影響を及ぼす可能性があります。
以下も軽量の DELETE
のパフォーマンスに悪影響を与える可能性があります:
DELETE
クエリ内の重いWHERE
条件。- ミューテーションキューが別の多くのミューテーションで埋まっている場合、これはテーブル上のすべてのミューテーションが順次実行されるため、パフォーマンスの問題につながる可能性があります。
- 影響を受けるテーブルに非常に多数のデータパーツがある。
- コンパクトパーツに多くのデータがある。コンパクトパーツでは、すべてのカラムが1つのファイルに保存されています。
削除権限
DELETE
には ALTER DELETE
権限が必要です。特定のユーザーの特定のテーブルで DELETE
ステートメントを有効にするには、以下のコマンドを実行します:
軽量の DELETE が ClickHouse 内でどのように機能するか
-
影響を受けた行に「マスク」が適用されます
DELETE FROM table ...
クエリが実行されると、ClickHouse は各行が「存在」または「削除済み」としてマークされるマスクを保存します。これらの「削除済み」行は、後続のクエリでは省略されます。しかし、行は実際には次のマージによってのみ削除されます。このマスクを書くことは、ALTER TABLE ... DELETE
クエリによって行われることに比べてはるかに軽量です。このマスクは、すべての可視行に対して
True
を、削除された行に対してFalse
を格納する隠れた_row_exists
システムカラムとして実装されています。このカラムは、パート内の行が削除されたときにのみそのパートに存在します。すべての値がTrue
に等しいパートにはこのカラムは存在しません。 -
SELECT
クエリはマスクを含めるように変換されますマスクされたカラムがクエリで使用されると、
SELECT ... FROM table WHERE condition
クエリは内部的に_row_exists
に対する述語によって拡張され、次のように変換されます:
実行時に、カラム _row_exists
が読まれ、返すべきでない行が決定されます。削除済みの行が多い場合、ClickHouse は残りのカラムを読み取る際に完全にスキップできるグラニュールを特定できます。
-
DELETE
クエリはALTER TABLE ... UPDATE
クエリに変換されますDELETE FROM table WHERE condition
は、ALTER TABLE table UPDATE _row_exists = 0 WHERE condition
ミューテーションに変換されます。内部的に、このミューテーションは2つのステップで実行されます:
-
各個々のパートに対して
SELECT count() FROM table WHERE condition
コマンドが実行され、そのパートが影響を受けているかどうかを確認します。 -
上記のコマンドに基づいて、影響を受けたパートがミューテーションされ、影響を受けていないパートのハードリンクが作成されます。幅の広いパートの場合、各行の
_row_exists
カラムが更新され、他のすべてのカラムのファイルがハードリンクされます。コンパクトパートの場合、すべてのカラムが1つのファイルにまとめて保存されているため、すべてのカラムが再書き込みされます。
上記のステップから、マスキング技術を用いた軽量の
DELETE
が、影響を受けるパートのすべてのカラムファイルを再書き込みせずにパフォーマンスを向上させることができることがわかります。 -