我有一个 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 FULL和ANALYZE。
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/