postgresql - 大表上的 Postgres UPDATE 非常慢

标签 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;

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

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

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

WITH内的查询只需要40秒。

上面引用的所有字段(A.X 和扩展名 B.X 除外)均按以下索引: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)

最佳答案

可能有多种解决方案。

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

关于postgresql - 大表上的 Postgres UPDATE 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9650290/

相关文章:

bash - 在 bash 命令行使用 psql 测试 postgresql 连接字符串?

sql - 在循环中使用 replace()

ruby-on-rails - 使用 Rails 3.1 ActiveRecord 查询查找年度日期

sql - PostgreSQL 10 Rowtype 功能错误?

php - Mysql - 如何从具有多个WHERE条件的另一个表更新表

mysql:当字段更新时如何自动更新时间戳

postgresql - 根据传递给 PostgreSQL 函数的列名数组获取行值

mysql - 增加 MySQL 中列的主键/唯一值

Mysql根据列输入动态更新行

mysql - 如何根据用户的第一次输入更新字段?