# DELETE文の構文

DELETE文は、テーブルから行を削除するために使用します。

DELETE文は、不正なデータ、重複データ、古いデータなど、不要な行を削除するのに役立ちます。

DELETE文は、TrinoとHiveの両方のクエリエンジンでサポートされています。

## 構文


```sql
DELETE FROM <table_name> WHERE <condition>
```

各項目について:

- <table_name> は削除対象のテーブル名です
- <condition> は検索条件を指定する句です


意図しないデータ削除の発生を抑えるため、`WHERE`句のない`DELETE`文は許可されていません。

### 例

航空便で出荷されたすべての品目を削除する例:


```sql
DELETE FROM lineitem WHERE shipmode = 'AIR'
```

2017年7月1日(UTC)のすべてのイベントログを削除する例:


```sql
DELETE FROM lineitem WHERE TD_TIME_RANGE(time, '2017-07-01','2017-07-02')
```

## 制限事項

### WHERE句のないDELETEは不可

意図しないデータ削除の発生を抑えるため、DELETE文ではWHERE句を含める必要があります。

エラーの例:


```
Does not support DELETE statement without WHERE condition
```

### Data Tankに対するDELETE

Data Tankに格納されているデータに対してDELETE文を発行することはできません。
Data Tankに格納されたデータに対してDELETE文を発行するには、PostgreSQL Data Tankに直接接続してください。

### 一度に削除できるパーティション数の上限

1つのDELETEクエリで削除できるパーティション数は最大500kです。
この上限を超えるとDELETEクエリは失敗します。

#### DELETE文の影響範囲を減らす

上限超過エラーやタイムアウトエラーでDELETEクエリが失敗した場合は、
影響範囲を減らすようにDELETE文を書き換えてください。
最も効果的な方法は、`TD_TIME_RANGE`または`TD_INTERVAL`を使ってDELETEの時間範囲を制限するWHERE句を追加することです。
たとえば、1年分のゲーム履歴データがある場合、次のクエリではなく、


```
DELETE FROM game_history WHERE player_id=1000;
```

次のように書き換えます。


```
DELETE FROM game_history
  WHERE player_id=1000
  AND TD_TIME_RANGE(time, '2018-01-01', '2018-02-01','PDT')
```

その後、すべての行が削除されるまで、時間範囲を変えながら削除を繰り返します。

### DELETE文のタイムアウトエラー

DELETE文の影響範囲が非常に大きい場合、DELETEクエリは数時間かかることがあります。
この場合、クエリがタイムアウトしてジョブが失敗することがあります。
タイムアウトエラーでジョブが失敗した場合は、影響範囲を減らすようにDELETE文を書き換えてください。
[DELETE文の影響範囲を減らす](#reduce-affected-rows-of-delete-statement)を参照してください。

### 同一テーブルに対する同時DELETE文は競合する可能性があります

同一テーブルに対して複数のDELETE文を同時に実行すると、
実行時間が長くなったり、クエリが失敗したりすることがあります。これは、
内部のパーティションファイル削除処理が競合するためです。一般的なガイドラインとして、
DELETE文の同時実行は避けることをおすすめします。競合の発生可能性は、
DELETE文の条件、データ量、テーブルのデータ分布など、さまざまな要因に依存し、予測が困難です。

競合によりDELETE文が失敗した場合は、クエリを再実行してください。

### DELETE文のリソース消費

DELETEクエリはジョブを発行し、リソースを消費します。Treasure Dataで使用されている
ストレージおよびインデックス方式の特性上、DELETEクエリはリソースを多く消費する場合があります。

DELETEクエリでフルテーブルスキャンが発生しないようにするには、以下を使用してください:

- テーブルがデフォルトの時間ベースパーティショニングを使用している場合は、TD_TIME_RANGEやTD_INTERVALなどの時間式
- テーブルがユーザー定義パーティショニングを使用している場合は、すべてのパーティションキーに対する等価述語


たとえば、テーブルが時間でパーティショニングされていて、2018年6月に作成されたユーザーセットを
削除しようとしている場合、それがDELETE文の重要なパラメーターでなくても、時間制約を含めてください。

たとえば、次のように記述します:


```
DELETE FROM logtable WHERE userid IN (1234, 1235, 1236) AND TD_TIME_RANGE(time, '2017-06-01','2017-07-01')
```

時間制約を含めることで、クエリの速度が大幅に向上し、消費するリソースも削減されます。

## DELETE文の取り消し

実行済みのDELETE文をロールバックして削除されたデータを復元したい場合は、
Treasure Dataテクニカルサポートに連絡し、実行されたDELETE文を含むジョブのジョブIDを提供する必要があります。
多くの場合、DELETE文を取り消すことができます。ただし、特定の状況ではDELETE文のロールバックができません。

ロールバックができない状況には、次のようなものがあります:

- 別のDELETE文によって新しいパーティションが削除されている場合。
- 保持期間の経過により、元のパーティションが破棄されている場合。
- テーブルが削除され、同じ名前で新しいテーブルが作成されている場合。
- 内部ストレージのメンテナンス処理の結果として、新しいパーティションがさらに変更または置き換えられている場合。