UPDATE pagelinks SET pl_to = page_id FROM page WHERE (pl_namespace,pl_title) = (page_namespace,page_title) AND page_is_redirect = 0 ;
EXPLAIN不是这里的问题,我只提到大表有多个索引,以便在某种程度上证明更新它需要多长时间.但无论如何这里是EXPLAIN:
Merge Join (cost=127710692.21..135714045.43 rows=452882848 width=57) Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?")) -> Sort (cost=3193335.39..3219544.38 rows=10483593 width=41) Sort Key: page.page_namespace,(page.page_title)::text -> Seq Scan on page (cost=0.00..439678.01 rows=10483593 width=41) Filter: (page_is_redirect = 0::numeric) -> Sort (cost=124517356.82..125285665.74 rows=307323566 width=46) Sort Key: pagelinks.pl_namespace,(pagelinks.pl_title)::text" -> Seq Scan on pagelinks (cost=0.00..6169460.66 rows=307323566 width=46)
现在我还发送了一个并行查询命令,以便DROP一个pagelinks的索引;当然它正在等待UPDATE完成(但我觉得无论如何都要尝试它!).因此,我无法从页面链接中选择任何内容,以免损坏数据(除非您认为杀死DROP INDEX postmaster进程是安全的?).
所以我想知道它们是否是一个可以跟踪死元组数量的表,因为知道UPDATE在完成任务时有多快或多远都会很好.
谢谢
(Postgresql并不像我想的那么聪明;它需要启发式)
我不是常规的Postgresql用户,但我只是阅读了该文档,然后与您正在显示的EXPLAIN输出进行比较.您的UPDATE查询似乎没有使用索引,并且它被迫执行表扫描以对页面和页面链接进行排序.毫无疑问,这种排序足以需要临时磁盘文件,我认为这些文件是在temp_tablespace下创建的.
然后我看到估计的数据库页面被读取. EXPLAIN输出的顶级显示(cost = 127710692.21..135714045.43).这里的单元是磁盘I / O访问.因此,它将访问磁盘超过1.35亿次来进行此更新.
请注意,即使是10,000rpm磁盘,寻道时间为5ms,在最佳条件下也可以达到每秒200次I / O操作.这意味着您的UPDATE将需要188小时(7.8天)的磁盘I / O,即使您可以在此期间维持饱和磁盘I / O(即连续读/写没有中断).这是不可能的,我希望实际的吞吐量至少减少一个数量级,特别是因为毫无疑问你在此期间使用这个服务器进行各种其他工作.所以我猜你只是通过UPDATE的一小部分.
如果是我,我会在第一天杀死这个查询,并找到了另一种执行UPDATE的方法,它更好地利用了索引并且不需要磁盘排序.您可能无法在单个sql语句中执行此操作.
至于你的DROP INDEX,我猜它只是阻塞,等待对表的独占访问,而当它处于这种状态时,我想你可能会杀掉它.