大表上的 Postgres UPDATE 非常慢

Are*_*bre 2 postgresql sql-update

我有一个 Postgres 9.1.3 表,在WHERE Y=1之后有 206 万行,如下所示(它总共只有几万行,没有任何WHERE)。我正在尝试使用如下查询将数据添加到空字段:

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;
Run Code Online (Sandbox Code Playgroud)

该查询运行了几个小时并且似乎进展非常缓慢。事实上,我第二次尝试此操作时,在查询运行约 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.
Run Code Online (Sandbox Code Playgroud)

查询在这些小时内几乎没有进展的解释是否正确?

在运行长查询之前,我已经完成了VACUUM FULLANALYZE 。

WITH内的查询只需要40秒。

除 AX 和扩展名 BX 之外,上面引用的所有字段均按以下索引:L、M、N、P、Y、Z。

该程序在配备 8 GB RAM、Core i7 Q720 1.6 GHz 四核处理器和 Windows 7 x64 的笔记本电脑上运行。我运行 Postgres 32 位是为了与 PostGIS 1.5.3 兼容。Windows 版 64 位 PostGIS 尚不可用。(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)
Run Code Online (Sandbox Code Playgroud)

man*_*iek 5

可能有多种解决方案。

  • 更新可能会被锁阻止。请参阅 pg_locks 视图。
  • 也许A上有触发器?它们可能是经济放缓的原因。
  • 尝试“解释更新...” - 该计划与普通选择的计划是否有显着不同?也许您可以分两步完成 - 将“B”导出到表,然后从该表进行更新。
  • 尝试在更新之前删除索引。
  • 创建一个新表,删除旧表,将新表重命名为旧表的名称。