2012-03-10 7 views
0

私は(それが唯一のより数万行がいかなるずに合計している)以下のとおりY = 1後に206万行のPostgresの9.1.3テーブルを持っています。非常に遅いPostgresのUPDATE

WITH B AS (
    SELECT Z, 
      rank() OVER (ORDER BY L, N, M, P) AS X 
    FROM A 
    WHERE Y=1 
) 

UPDATE A 
SET A.X = B.X 
FROM B 
WHERE A.Y=1 
    AND B.Z = A.Z; 

このクエリは数時間実行され、非常にゆっくりと処理されているように見えますが、空のフィールドにデータを追加しようとしています。実際、私がこれを試したのは2回目ですが、クエリが約3時間実行された後に停電が発生しました。電源を復元した後、私はテーブルを分析し、この得た:

INFO: analyzing "consistent.master" 
INFO: "master": scanned 30000 of 69354 pages, containing 903542 live rows and 153552 dead rows; 30000 rows in sample, 2294502 estimated total rows 
Total query runtime: 60089 ms. 

それはクエリがかろうじてそれらの時間で進行したことを解釈するには正しいですか?

私はが長いクエリを実行する前にをANALYZE FULL VACUUMを行っています。

WITHのクエリには40秒かかります。

すべてのフィールドは、AXを除き上記で参照し、拡張BXにより、索引付けさ:L、M、N、P、Y、Zの

これは、8ギガバイトRAM、コアI7とラップトップ上で実行されていますQ720 1.6 GHzクアッドコアプロセッサ、およびWindows 7 x64が含まれます。 Postgres 1.5.3との互換性のためにPostgres 32ビットを実行しています。 64ビットPostGIS for Windowsはまだ利用できません。 (32ビットPostgresが、それはWindowsで2 GB以上のRAMを使用することはできませんが、私はそれがここでの問題だ疑い)ここで

は、EXPLAINの結果です:

Update on A (cost=727684.76..945437.01 rows=2032987 width=330) 
    CTE B 
    -> WindowAgg (cost=491007.50..542482.47 rows=2058999 width=43) 
      -> Sort (cost=491007.50..496155.00 rows=2058999 width=43) 
       Sort Key: A.L, A.N, A.M, A.P 
       -> Seq Scan on A (cost=0.00..85066.80 rows=2058999 width=43) 
         Filter: (Y = 1) 
    -> Hash Join (cost=185202.29..402954.54 rows=2032987 width=330) 
     Hash Cond: ((B.Z)::text = (A.Z)::text) 
     -> CTE Scan on B (cost=0.00..41179.98 rows=2058999 width=88) 
     -> Hash (cost=85066.80..85066.80 rows=2058999 width=266) 
       -> Seq Scan on A (cost=0.00..85066.80 rows=2058999 width=266) 
        Filter: (Y = 1) 
+0

私は数字を理解していません。テーブルには200万行が含まれています。 'WHERE Y = 1'という条件からいくつの行が選択されますか? –

+2

'EXPLAIN'を投稿するか、完了したら' EXPLAIN ANALYZE'出力してください。 –

+0

'Y = 1 '部分が(私のランダムに生成されたデータのように)非常に選択的な場合、更新はミリ秒以内に行われます。したがって、データの[sscce.org](http://sscce.org/)の例を提供してください。 –

答えて

2

複数のソリューションがあるかもしれません。

  • 更新プログラムはロックでブロックされる可能性があります。 pg_locksビューに問い合わせてください。
  • おそらくAにトリガがありますか?彼らは減速の理由になる可能性があります。
  • 「説明を更新してください...」と試してみてください - プレーン・セレクトのプランとは大きく異なるプランですか?多分あなたは2つのステップでそれを行うことができます - テーブルに "B"をエクスポートし、そのテーブルから更新してください。
  • 更新前にインデックスを削除してみます。
  • 新しいテーブルを作成し、古いテーブルを削除し、新しいテーブルの名前を古いテーブルの名前に変更します。
+0

私の賭けは(b)ロックの問題です。私はかなり古くなったデスクトップでアップデートを試し、元のステートメントで200万行を更新するのに〜4分かかりました。 –

+0

私はこのDBの唯一のユーザーです。それは(b)ロックを排除しないだろうか?トリガーはありません。 EXPLAINの結果は私の編集した投稿にあります。私はそれがUDPATEとSELECTを分けると思いますか? 2番目のテーブルについての良い考え。私は今日後でそれを試すことができるかどうかを見ていきます。 –

+0

「更新前にインデックスを削除する」と書いただけです。物事を悪化させないだろうか?更新されたフィールド(** A.X **)はインデックスに登録されていません。** ** A.Y **および** A.Z **に関する** WHERE **節があります。 –

0

は、このようなクエリを書き換えるようにしてください:

UPDATE A 
SET A.X = B.X 
FROM B 
WHERE A.Y=1 
     AND B.Z = A.Z 
     AND A.X IS DISTINCT FROM B.X;