我一直在一个包含2.5亿行和3个索引的表上运行UPDATE';此UPDATE使用另一个包含3000万行的表。现在已经运行了大约36个小时。我想知道如果他们计划花费一百万天来完成它的事情,他们是否有办法找出完成的距离,我会杀了它;但如果它只需要一两天,我会让它运行。这是命令查询:

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)

现在我还发送了一个并行查询命令,以便删除其中一个 pagelinks'索引;当然它正在等待UPDATE完成(但我觉得无论如何都要尝试它!)。因此,我无法从 pagelinks 中选择任何内容,以免损坏数据(除非您认为杀死DROP INDEX postmaster进程是安全的?)。

所以我想知道它们是否是一个可以跟踪死元组数量的表,因为知道UPDATE在完成任务时有多快或多远都会很好。

THX (PostgreSQL并不像我想象的那么聪明;它需要启发式算法)

有帮助吗?

解决方案

您是否阅读过PostgreSQL文档“使用EXPLAIN ",解释你正在显示的输出?

我不是常规的PostgreSQL用户,但我只是阅读了该文档,然后将其与您正在显示的 EXPLAIN 输出进行比较。您的 UPDATE 查询似乎没有使用索引,并且它被迫执行表扫描以对 page pagelinks 进行排序。毫无疑问,这种排序足以需要临时磁盘文件,我认为这些文件是在 temp_tablespace 下创建的。

然后我看到估计的数据库页面被读取。该 EXPLAIN 输出的顶级显示(cost = 127710692.21..135714045.43)。这里的单元是磁盘I / O访问。所以它将访问磁盘超过1.35亿次来执行 UPDATE

请注意,即使是10,000rpm磁盘,寻道时间为5ms,在最佳条件下也可以达到每秒200次I / O操作。这意味着您的 UPDATE 将需要188小时(7.8天)的磁盘I / O,即使您可以在此期间维持饱和磁盘I / O(即连续读/写没有中断) 。这是不可能的,我希望实际的吞吐量至少减少一个数量级,特别是因为毫无疑问你在此期间一直使用这台服务器进行各种其他工作。所以我猜你只是通过 UPDATE 的一小部分。

如果是我,我会在第一天杀死这个查询,并找到另一种执行 UPDATE 的方法,它可以更好地使用索引并且不需要磁盘排序。您可能无法在单个SQL语句中执行此操作。

至于你的 DROP INDEX ,我猜它只是阻塞,等待对表的独占访问,当它处于这种状态时,我想你可能会杀掉它。

其他提示

这是非常古老的,但是如果你想要一种方法来监视你的更新...请记住序列是全局影响的,所以你只需创建一个以在另一个会话中监视此更新:

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

然后在另一个会话中执行此操作(不要担心事务,因为序列受全局影响):

select last_value from yourprogress;

这将显示受影响的行数,因此您可以估计需要多长时间。

刚刚重新开始你的序列再试一次:

alter sequence yourprogress restart with 1;

或者只是放弃它:

drop sequence yourprogress;

你需要索引,或者比尔指出,它需要对所有表进行顺序扫描。

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top