DELETE ステートメントは、式 expr に一致するテーブル [db.]table の行を削除します。これは *MergeTree テーブルエンジンファミリーでのみ使用できます。
例
論理削除 ではデータはすぐには削除されません
論理削除 は、行を削除済みとしてマークしますが、ストレージからはすぐに削除しません。デフォルトでは、ミューテーション を使用します。lightweight_delete_mode の設定によっては、パッチパートを使用することもできます。
デフォルトのミューテーション方式では、DELETE ステートメントは、行を削除済みとしてマークする処理が完了するまで待機してから戻ります。データ量が多い場合、この処理には時間がかかることがあります。あるいは、設定 lightweight_deletes_sync を使用して、バックグラウンドで非同期に実行することもできます。これを無効にすると、DELETE ステートメントはすぐに戻りますが、バックグラウンドの ミューテーション が完了するまでは、データがクエリから見え続ける可能性があります。
どちらの方式でも、削除済みの行はクリーンアップされるまでストレージに残ります。通常は、バックグラウンドマージによって、影響を受けるデータパーツから削除されます。削除マスクを明示的に適用するには、負荷の高いミューテーションを実行する ALTER TABLE ... APPLY DELETED MASK を使用してください。
データが予測可能な時間内にストレージから確実に削除されるようにしたい場合は、テーブル設定 min_age_to_force_merge_seconds の使用を検討してください。あるいは、ALTER TABLE … DELETE コマンドを使用することもできます。ALTER TABLE ... DELETE によるデータ削除では、影響を受けるすべてのパーツを再作成するため、大量のリソースを消費する可能性がある点に注意してください。
削除モードを選択する
lightweight_delete_mode 設定では、ミューテーションベースの削除 (デフォルト) か、削除対象の行について _row_exists = 0 を含むパッチパートを書き込む論理更新を選択します。クエリでは、物理的なクリーンアップが行われる前に、これらのパッチが適用されます。
利用可能なモードは設定のリファレンスを、前提条件は論理更新の要件を参照してください。パッチパートを使用する場合、lightweight_deletes_sync は他のレプリカへの反映を待ちません。ReplicatedMergeTree では、他のレプリカがパッチを受信するまで、削除済みの行が返されることがあります。
大量のデータの削除
大量の削除は ClickHouse のパフォーマンスに悪影響を与える可能性があります。テーブル内のすべての行を削除したい場合は、TRUNCATE TABLE コマンドの使用を検討してください。
削除が頻繁に発生することが見込まれる場合は、カスタムのパーティションキーの使用を検討してください。これにより、ALTER TABLE ... DROP PARTITION コマンドを使って、そのパーティションに関連するすべての行をすばやく削除できます。
論理削除 の制約
プロジェクションがある場合の論理削除
デフォルトでは、DELETE はプロジェクションを持つテーブルでは使用できません。これは、プロジェクション内の行が DELETE 操作の影響を受ける可能性があるためです。ただし、この挙動は MergeTree 設定 lightweight_mutation_projection_mode で変更できます。
論理削除 使用時のパフォーマンスに関する考慮事項
論理削除 ステートメントで大量のデータを削除すると、SELECT クエリのパフォーマンスに悪影響を及ぼす可能性があります。 また、次の要因も論理削除 のパフォーマンスに悪影響を与える可能性があります。DELETEクエリ内の負荷の高いWHERE条件。- ミューテーションベースの削除の場合、ミューテーションキューが大きいこと。テーブル上のミューテーションは順次実行されます。
- 対象のテーブルに非常に多くのデータパーツがある。
- ミューテーションベースの削除を使用する場合、compact パーツに大量のデータがあること。compact パーツでは、すべてのカラムが 1 つのファイルに格納されており、まとめて書き直す必要があります。
DELETE 権限
DELETE を実行するには、ALTER DELETE 権限が必要です。特定のユーザーが特定のテーブルで DELETE ステートメントを実行できるようにするには、次のコマンドを実行します。
ClickHouse における論理削除の内部的な仕組み
-
影響を受ける行に「マスク」が適用される
DELETE FROM table ...クエリが実行されると、ClickHouse は各行が「existing」か「deleted」かを示すマスクを保存します。以降のクエリでは、「deleted」とマークされた行は除外されます。ただし、行が物理的に削除されるのは後で、通常はバックグラウンドマージ時です。このマスクの書き込みは、ALTER TABLE ... DELETEクエリで行われる処理に比べてはるかに軽量です。 このマスクは、可視状態のすべての行にTrue、削除された行にFalseを格納する隠しシステムカラム_row_existsとして実装されています。このカラムは、パーツ内で一部の行が削除されている場合にのみ存在します。パーツ内のすべての値がTrueの場合、このカラムは存在しません。 -
SELECTクエリはマスクを含む形に変換される マスク対象のカラムがクエリで使用される場合、SELECT ... FROM table WHERE conditionクエリには内部的に_row_existsに対する述語が追加され、次のように変換されます。実行時には、返すべきでない行を判定するために_row_existsカラムが読み取られます。削除された行が多い場合、ClickHouse は残りのカラムを読む際に、どの granule を完全にスキップできるかを判断できます。 -
DELETEクエリは選択したモードに応じてマスクを更新する パッチパートを使用する場合、DELETE FROM table WHERE conditionはUPDATE table SET _row_exists = 0 WHERE conditionに変換されます。生成されたパッチパートには削除された行のマスクの変更が格納され、データの読み取り時とマージ時に適用されます。 デフォルトのalter_updateモードでは、DELETE FROM table WHERE conditionはALTER TABLE table UPDATE _row_exists = 0 WHERE conditionミューテーションに変換されます。 内部的には、このミューテーションは次の 2 段階で実行されます。-
各パーツが影響を受けるかどうかを判定するため、各パーツごとに
SELECT count() FROM table WHERE conditionコマンドが実行されます。 -
上記のコマンドの結果に基づいて、影響を受けるパーツにはミューテーションが適用され、影響を受けないパーツにはハードリンクが作成されます。wide パーツ の場合は各行の
_row_existsカラムが更新され、その他のすべてのカラムのファイルにはハードリンクが作成されます。compact パーツ の場合はすべてのカラムが 1 つのファイルにまとめて格納されているため、すべてのカラムが再書き込みされます。
DELETEは、影響を受けるパーツに対してすべてのカラムファイルを書き直す必要がないため、従来のALTER TABLE ... DELETEよりも高い性能を発揮することがわかります。 -
各パーツが影響を受けるかどうかを判定するため、各パーツごとに
関連コンテンツ
- ブログ: ClickHouseにおける更新と削除の扱い
- ブログ: 論理削除がさらに軽量に