The Lightweight DELETE Statement
軽量の DELETE
ステートメントは、式 expr
に一致する行をテーブル [db.]table
から削除します。これは MergeTree テーブルエンジンファミリー のみで使用可能です。
これは、重たいプロセスである ALTER TABLE ... DELETE コマンドとの対比から「軽量 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
ステートメントを有効にするには、以下のコマンドを実行してください:
ClickHouse 内部での軽量 DELETE の動作
-
影響を受けた行に「マスク」が適用される
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
がマスキング技術を使用することで、伝統的なALTER TABLE ... DELETE
に比べてパフォーマンスを改善することができることが分かります。これは、影響を受けたパートのすべてのカラムファイルを再書き込みしないためです。 -