[解決済み] 数百万行をIDで削除する最適な方法
質問
PG データベースから約 200 万行を削除する必要があります。私は、削除する必要がある ID のリストを持っています。しかし、私がこれをしようとするどの方法も、何日もかかっています。
私はそれらをテーブルに入れ、100 のバッチでそれを行うことを試みました。4 日後、これはまだ実行中で、297268 行しか削除されていません。(ID テーブルから 100 の ID を選択し、そのリストの中のどこを削除し、選択した 100 を ID テーブルから削除しなければなりませんでした)。
私は試しました。
DELETE FROM tbl WHERE id IN (select * from ids)
これも時間がかかっていますね。完了するまで進行状況を見ることができないので、どのくらいかかるのか計りかねますが、2日経ってもクエリが実行されたままでした。
削除する特定の ID がわかっていて、ID が何百万もある場合に、テーブルから削除する最も効果的な方法を探しているところなんです。
どのように解決するのですか?
それはすべて...
-
仮定すると 同時書き込みアクセスなし を使用しないか、テーブルを排他的にロックしなければならないか、あるいはこのルートは全く向いていないかもしれません。
-
すべてのインデックスを削除します(おそらく削除自体に必要なものを除く)。
その後、それらを再作成します。これは通常、インデックスへの増分更新よりもはるかに高速です。 -
一時的に安全に削除/無効化できるトリガーがあるかどうかを確認します。
-
外部キーはあなたのテーブルを参照していますか?それらは削除可能ですか?一時的に削除されますか?
-
autovacuum の設定によって、それは は を実行するのに役立ちます。
VACUUM ANALYZE
を実行するのに役立つかもしれません。 -
マニュアルの関連章に記載されているポイントの一部 データベースへの入力 も、設定次第では役に立つかもしれません。
-
テーブルの大部分を削除し、残りが RAM に収まる場合、最も高速で簡単な方法はこれかもしれません。
BEGIN; -- typically faster and safer wrapped in a single transaction
SET LOCAL temp_buffers = '1000MB'; -- enough to hold the temp table
CREATE TEMP TABLE tmp AS
SELECT t.*
FROM tbl t
LEFT JOIN del_list d USING (id)
WHERE d.id IS NULL; -- copy surviving rows into temporary table
-- ORDER BY ? -- optionally order favorably while being at it
TRUNCATE tbl; -- empty table - truncate is very fast for big tables
INSERT INTO tbl
TABLE tmp; -- insert back surviving rows.
COMMIT;
この方法では、ビュー、外部キー、その他の依存するオブジェクトを再作成する必要がありません。そして、肥大化することなく、原始的な(ソートされた)テーブルを手に入れることができます。
について読む
temp_buffers
の設定については、マニュアル
. この方法は、テーブルがメモリに収まる限り、あるいは少なくともそのほとんどが収まる限り、高速に動作します。トランザクションラッパーは、この操作の途中でサーバーがクラッシュした場合にデータを失わないようにするものです。
実行
VACUUM ANALYZE
を後に実行します。または(通常
ではない
を行った後に必要な
TRUNCATE
ルート)
VACUUM FULL ANALYZE
で最小サイズになります(排他ロックが必要です)。大きなテーブルの場合は、代替案として
CLUSTER
/
pg_repack
などとする。
小さなテーブルの場合、単純な
DELETE
の代わりに
TRUNCATE
の方が速い場合が多いです。
DELETE FROM tbl t
USING del_list d
WHERE t.id = d.id;
読む
その
ノート
セクションで
TRUNCATE
マニュアルにある
. 特に、(
Pedro もコメントで指摘しているように
):
TRUNCATE
は、他のテーブルからの外部キー参照を持つテーブルでは使用できません。 他のテーブルからの外部キー参照を持つテーブルでは、そのようなテーブルもすべて同じコマンドで切り捨てられない限り、使用できません。 ただし、そのようなテーブルがすべて同じコマンドで切り捨てられる場合はこの限りではありません。[...]
とか。
<ブロッククオート
TRUNCATE
は、いかなる
ON DELETE
トリガーを起動しない。
を起動しません。
関連
-
[解決済み] Oracleで上位100行を選択する方法は?
-
[解決済み] SQL ServerでSELECTからUPDATEする方法とは?
-
[解決済み] データベースのインデックス作成はどのように行われるのですか?[クローズド]
-
[解決済み] SQL Server で複数行のテキストを 1 つのテキスト文字列に連結する方法
-
[解決済み] MySQLの複数行を1つのフィールドに連結することはできますか?
-
[解決済み] SQL Server - 挿入された行のIDを取得するための最良の方法は?
-
[解決済み] SQL Server の CASE ステートメントで OR がサポートされていない。
-
[解決済み] T-SQL文の接頭辞Nの意味と使うべきタイミングは?
-
[解決済み] ランダムな行を選択する最適な方法 PostgreSQL
-
[解決済み] SQL ServerでINNER JOINを使用して削除するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
MHAクラスタエラーサマリーの構築
-
[解決済み] SQLのカラム名があいまいな場合のクエリエラー
-
[解決済み] SQL Serverで実行中の合計を計算する
-
[解決済み] MySQLの「スキーマの作成」と「データベースの作成」 - 違いはあるのか?
-
[解決済み] SQL Server : 列を行に変換する
-
[解決済み] 複数の列でgroup byを使用する
-
[解決済み] SQL Serverにおける関数とストアドプロシージャの比較
-
[解決済み] SQL Serverで、指定したテーブルを参照しているすべての外部キーを一覧表示するにはどうすればよいですか?
-
[解決済み] T-SQLでnot equalには!=と<>のどちらを使うべきですか?
-
[解決済み] SQL Server の CASE ステートメントで OR がサポートされていない。