11

PostgreSQLでは、次のようなクエリがあり、1mの行テーブルから25万行が削除されます。

DELETE FROM table WHERE key = 'needle';

クエリの実行には1時間以上かかり、その間、影響を受ける行は書き込み用にロックされます。これは、多くの更新クエリが大きな削除クエリが完了するのを待たなければならないことを意味するため、良くありません(その後、行が下から消えたために失敗しますが、それは問題ありません)。この大きなクエリを複数の部分に分割して、更新クエリへの干渉をできるだけ少なくする方法が必要です。たとえば、削除クエリをそれぞれ1000行のチャンクに分割できる場合、他の更新クエリは最大で1000行を含む削除クエリを待機する必要があります。

DELETE FROM table WHERE key = 'needle' LIMIT 10000;

そのクエリはうまく機能しますが、残念ながらpostgresには存在しません。

4

3 に答える 3

33

副選択を試して、一意の条件を使用してください。

DELETE FROM 
  table 
WHERE 
  id IN (SELECT id FROM table WHERE key = 'needle' LIMIT 10000);
于 2010-08-06T05:55:58.443 に答える
2

Frakの答えは良いですが、これはより高速になる可能性がありますが、ウィンドウ関数のサポート(擬似コード)のために8.4が必要です。

result = query('select
    id from (
        select id, row_number(*) over (order by id) as row_number
        from mytable where key=?
    ) as _
    where row_number%8192=0 order by id, 'needle');
// result contains ids of every 8192nd row which key='needle'
last_id = 0;
result.append(MAX_INT); // guard
for (row in result) {
    query('delete from mytable
        where id<=? and id>? and key=?, row.id, last_id, 'needle');
    // last_id is used to hint query planner,
    // that there will be no rows with smaller id
    // so it is less likely to use full table scan
    last_id = row.id;
}

これは時期尚早の最適化です—邪悪なことです。注意してください。

于 2010-08-06T15:38:12.853 に答える
2

削除と更新のロック レベルをより詳細なロック モードに設定します。トランザクションが遅くなることに注意してください。

http://www.postgresql.org/docs/current/static/sql-lock.html

http://www.postgresql.org/docs/current/static/explicit-locking.html

于 2010-08-06T06:30:06.950 に答える