軽量削除ステートメント
軽量の 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
よりもパフォーマンスが向上することがわかります。 -