8.2 KiB
slug | sidebar_position | sidebar_label | description | keywords | title | |
---|---|---|---|---|---|---|
/ja/sql-reference/statements/delete | 36 | DELETE | 論理削除は、データベースからデータを削除するプロセスを簡素化します。 |
|
論理 DELETE 文 |
論理削除は、MergeTree テーブルエンジンファミリにのみ利用可能で、式 expr
に一致する [db.]table
から行を削除します。
DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;
これは、ALTER TABLE ... DELETE コマンドとの対比で「論理 削除
」と呼ばれていますが、ALTER コマンドは重いプロセスです。
例
-- `Title` カラムが `hello` を含む `hits` テーブルからすべての行を削除
DELETE FROM hits WHERE Title LIKE '%hello%';
論理削除はデータを即座に削除しない
論理 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
操作によって影響される可能性があるためです。しかし、この動作を変更する MergeTree 設定 lightweight_mutation_projection_mode
があります。
論理削除を使用する際のパフォーマンス考慮事項
論理DELETE
文を使用して大量のデータを削除すると、SELECT クエリのパフォーマンスに悪影響を与える可能性があります。
次の点も論理 DELETE
のパフォーマンスにマイナスの影響を与える可能性があります:
DELETE
クエリで重いWHERE
条件がある。- ミューテーションキューが他の多くのミューテーションで満たされている場合、テーブルのすべてのミューテーションは順に実行されるため、パフォーマンスの問題につながる可能性があります。
- 影響を受けたテーブルに非常に多くのデータパーツがある。
- コンパクトパーツに大量のデータがある場合。コンパクトパーツでは、すべてのカラムが1つのファイルに保存されます。
削除の権限
DELETE
には ALTER DELETE
権限が必要です。指定したユーザーに対して特定のテーブルで DELETE
文を有効にするには、次のコマンドを実行します:
GRANT ALTER DELETE ON db.table to username;
ClickHouse 内部での論理削除の動作
-
影響を受けた行に「マスク」が適用される
DELETE FROM table ...
クエリが実行されると、ClickHouse は各行に “existing” と “deleted” のいずれかでマークされたマスクを保存します。これらの “deleted” 行は、後続のクエリでは省略されます。しかし、行は実際には後続のマージによってのみ削除されます。このマスクの書き込みは、ALTER TABLE ... DELETE
クエリが行うものよりも軽量です。このマスクは、隠された
_row_exists
システムカラムとして実装され、すべての表示行に対してTrue
を、削除された行に対してはFalse
を格納します。このカラムは、パーツ内で一部の行が削除された場合にのみ存在します。このカラムは、すべての値がTrue
である場合には存在しません。 -
SELECT
クエリはマスクを組み込むように変換されるマスクされたカラムがクエリで使用されると、
SELECT ... FROM table WHERE condition
クエリは内部的に_row_exists
に対する述語で拡張され、次のように変換されます:SELECT ... FROM table PREWHERE _row_exists WHERE condition
実行時に、カラム
_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
カラムが更新され、他のすべてのカラムのファイルはハードリンクされます。コンパクトパーツの場合、すべてのカラムが一つのファイルに一緒に保存されているため、すべてのカラムが再書き込みされます。
上記の手順から、マスキング技術を使用した論理
DELETE
は、影響を受けたパーツのすべてのカラムファイルを再書き込みしないため、従来のALTER TABLE ... DELETE
に比べてパフォーマンスを改善していることがわかります。 -