> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 削除ミューテーション

> 削除によってテーブルデータを操作する ALTER クエリである削除ミューテーションを説明するページ

削除ミューテーションとは、削除によってテーブルデータを操作する `ALTER` クエリのことです。代表的なものとして、`ALTER TABLE DELETE` などがあります。こうしたクエリを実行すると、データパーツの新しいミューテーション済みバージョンが生成されます。つまり、このようなステートメントは、ミューテーションより前に挿入されたすべてのデータについてデータパーツ全体の書き換えをトリガーするため、大量の書き込みリクエストが発生します。

<Info>
  削除では、デフォルトの MergeTree テーブルエンジンの代わりに、[ReplacingMergeTree](/ja/concepts/features/operations/update/replacing-merge-tree) や [CollapsingMergeTree](/ja/reference/engines/table-engines/mergetree-family/collapsingmergetree) などの専用テーブルエンジンを使用することで、こうした大量の書き込みリクエストを回避できます。
</Info>

論理 `DELETE` ステートメントは、式 `expr` に一致するテーブル `[db.]table` の行を削除します。これは \*MergeTree テーブルエンジンファミリーでのみ使用できます。

```sql theme={null}
DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;
```

これは、負荷の大きい [ALTER TABLE ... DELETE](/ja/reference/statements/alter/delete) コマンドと区別するために、「論理削除」と呼ばれます。

<div id="examples">
  ## 例
</div>

```sql theme={null}
-- `hits` テーブルから `Title` カラムに `hello` というテキストを含むすべての行を削除する
DELETE FROM hits WHERE Title LIKE '%hello%';
```

<div id="lightweight-delete-does-not-delete-data-immediately">
  ## 論理削除 ではデータはすぐには削除されません
</div>

論理削除 は、行を削除済みとしてマークするものの、ただちに物理的に削除はしない [ミューテーション](/ja/reference/statements/alter#mutations) として実装されています。

デフォルトでは、`DELETE` ステートメントは、行を削除済みとしてマークする処理が完了するまで待機してから戻ります。データ量が多い場合、この処理には時間がかかることがあります。あるいは、設定 [`lightweight_deletes_sync`](/ja/reference/settings/session-settings#lightweight_deletes_sync) を使用して、バックグラウンドで非同期に実行することもできます。これを無効にすると、`DELETE` ステートメントはすぐに戻りますが、バックグラウンドの ミューテーション が完了するまでは、データがクエリから見え続ける可能性があります。

この ミューテーション では、削除済みとしてマークされた行は物理的には削除されません。実際に削除されるのは、次回の merge 時のみです。そのため、一定期間のあいだ、データは実際にはストレージから削除されず、削除済みとしてマークされているだけの状態になる可能性があります。

データが予測可能な時間内にストレージから確実に削除されるようにしたい場合は、テーブル設定 [`min_age_to_force_merge_seconds`](/ja/reference/settings/merge-tree-settings#min_age_to_force_merge_seconds) の使用を検討してください。あるいは、[ALTER TABLE ... DELETE](/ja/reference/statements/alter/delete) コマンドを使用することもできます。`ALTER TABLE ... DELETE` によるデータ削除では、影響を受けるすべてのパーツを再作成するため、大量のリソースを消費する可能性がある点に注意してください。

<div id="deleting-large-amounts-of-data">
  ## 大量のデータの削除
</div>

大量の削除は ClickHouse のパフォーマンスに悪影響を与える可能性があります。テーブル内のすべての行を削除したい場合は、[`TRUNCATE TABLE`](/ja/reference/statements/truncate) コマンドの使用を検討してください。

削除が頻繁に発生することが見込まれる場合は、[カスタムのパーティションキー](/ja/reference/engines/table-engines/mergetree-family/custom-partitioning-key)の使用を検討してください。これにより、[`ALTER TABLE ... DROP PARTITION`](/ja/reference/statements/alter/partition#drop-partitionpart) コマンドを使って、そのパーティションに関連するすべての行をすばやく削除できます。

<div id="limitations-of-lightweight-delete">
  ## 論理削除 の制約
</div>

<div id="lightweight-deletes-with-projections">
  ### プロジェクションがある場合の論理削除
</div>

デフォルトでは、`DELETE` はプロジェクションを持つテーブルでは使用できません。これは、プロジェクション内の行が `DELETE` 操作の影響を受ける可能性があるためです。ただし、この挙動は [MergeTree 設定](/ja/reference/settings/merge-tree-settings) `lightweight_mutation_projection_mode` で変更できます。

<div id="performance-considerations-when-using-lightweight-delete">
  ## 論理削除 使用時のパフォーマンスに関する考慮事項
</div>

**論理削除 ステートメントで大量のデータを削除すると、SELECT クエリのパフォーマンスに悪影響を及ぼす可能性があります。**

また、次の要因も論理削除 のパフォーマンスに悪影響を与える可能性があります。

* `DELETE` クエリ内の負荷の高い `WHERE` 条件。
* ミューテーションキューが多数の他のミューテーションで埋まっている場合、テーブル上のすべてのミューテーションは順次実行されるため、パフォーマンスの問題につながる可能性があります。
* 対象のテーブルに非常に多くのデータパーツがある。
* compact パーツに大量のデータがあること。compact パーツでは、すべてのカラムが 1 つのファイルに格納されます。

<div id="delete-permissions">
  ## DELETE 権限
</div>

`DELETE` を実行するには、`ALTER DELETE` 権限が必要です。特定のユーザーが特定のテーブルで `DELETE` ステートメントを実行できるようにするには、次のコマンドを実行します。

```sql theme={null}
GRANT ALTER DELETE ON db.table to username;
```

<div id="how-lightweight-deletes-work-internally-in-clickhouse">
  ## ClickHouse における論理削除の内部的な仕組み
</div>

1. **影響を受ける行に「マスク」が適用される**

   `DELETE FROM table ...` クエリが実行されると、ClickHouse は各行が「existing」か「deleted」かを示すマスクを保存します。以降のクエリでは、「deleted」とマークされた行は除外されます。ただし、行が実際に削除されるのは、その後のマージ時です。このマスクの書き込みは、`ALTER TABLE ... DELETE` クエリで行われる処理に比べてはるかに軽量です。

   このマスクは、可視状態のすべての行に `True`、削除された行に `False` を格納する隠しシステムカラム `_row_exists` として実装されています。このカラムは、パーツ内で一部の行が削除されている場合にのみ存在します。パーツ内のすべての値が `True` の場合、このカラムは存在しません。

2. **`SELECT` クエリはマスクを含む形に変換される**

   マスク対象のカラムがクエリで使用される場合、`SELECT ... FROM table WHERE condition` クエリには内部的に `_row_exists` に対する述語が追加され、次のように変換されます。

   ```sql theme={null}
   SELECT ... FROM table PREWHERE _row_exists WHERE condition
   ```

   実行時には、返すべきでない行を判定するために `_row_exists` カラムが読み取られます。削除された行が多い場合、ClickHouse は残りのカラムを読む際に、どの granule を完全にスキップできるかを判断できます。

3. **`DELETE` クエリは `ALTER TABLE ... UPDATE` クエリに変換される**

   `DELETE FROM table WHERE condition` は、`ALTER TABLE table UPDATE _row_exists = 0 WHERE condition` ミューテーションに変換されます。

   内部的には、このミューテーションは次の 2 段階で実行されます。

   1. 各パーツが影響を受けるかどうかを判定するため、各パーツごとに `SELECT count() FROM table WHERE condition` コマンドが実行されます。

   2. 上記のコマンドの結果に基づいて、影響を受けるパーツにはミューテーションが適用され、影響を受けないパーツにはハードリンクが作成されます。wide パーツ の場合は各行の `_row_exists` カラムが更新され、その他のすべてのカラムのファイルにはハードリンクが作成されます。compact パーツ の場合はすべてのカラムが 1 つのファイルにまとめて格納されているため、すべてのカラムが再書き込みされます。

   以上の手順から、マスキング手法を用いた論理削除の `DELETE` は、影響を受けるパーツに対してすべてのカラムファイルを書き直す必要がないため、従来の `ALTER TABLE ... DELETE` よりも高い性能を発揮することがわかります。

<div id="related-content">
  ## 関連コンテンツ
</div>

* ブログ: [ClickHouseにおける更新と削除の扱い](https://clickhouse.com/blog/handling-updates-and-deletes-in-clickhouse)
