耗时 SQL 更新语句

Time Consuming SQL Update Statement

在 Postgresql(版本 9.2)中,我需要用另一个 table 的值更新一个 table。下面的 UPDATE 语句适用于小型数据集(1K 记录)并快速完成。记录量大(600K+),超过两个小时语句还没有完成。不知道是时间长了还是挂了。

UPDATE training_records r SET cid = 
   (SELECT cid_main FROM account_events e 
    WHERE e.user_ekey = r.ekey 
    AND e.type = 't' 
    AND r.enroll_date < e.time 
    ORDER BY e.time ASC LIMIT 1) 
WHERE r.cid IS NULL;    

这个说法有问题吗?有没有更有效的方法来做到这一点?

关于操作: training_records 保存分组的会员帐户(id by ekey)的课程注册记录。 cid 是群号。 account_events 保存帐户更改事件,包括组之间的转移 (e.type='t'),其中 cid_main 将是转移前的组 ID。我正在尝试追溯修补 training_records 中新添加的 cid 列,以便它准确反映课程注册时的组成员身份。可能有多次转移,所以我从注册后最早的转移中选择组 ID (cid_main)。希望这是有道理的。

table training_records 有近 700K 条记录,account_events 有 560K+ 条记录。

EXPLAIN {以上命令}的输出

 Update on training_records r  (cost=0.00..13275775666.76 rows=664913 width=74)
   ->  Seq Scan on training_records r  (cost=0.00..13275775666.76 rows=664913 width=74)
         Filter: (cid IS NULL)
         SubPlan 1
           ->  Limit  (cost=19966.15..19966.16 rows=1 width=12)
                 ->  Sort  (cost=19966.15..19966.16 rows=1 width=12)
                       Sort Key: e."time"
                       ->  Seq Scan on account_events e  (cost=0.00..19966.15 rows=1 width=12)
                             Filter: ((r.enroll_date < "time") AND (user_ekey = r.ekey) AND (type = 't'::bpchar))
(9 rows)

再更新一次: 在 WHERE 中添加一个附加条件,我将记录数从 training_records 限制在 10K 左右。更新大约需要 15 分钟。如果时间与这个 table 的记录数接近线性关系,700K 条记录大约需要 17 个小时以上。

感谢您的帮助!

更新:花了将近9个小时,但是原来的命令完成了。

尝试将其转换为不强制嵌套循环连接的内容:

UPDATE training_records r
SET cid = e.cid_main
FROM account_events e
WHERE e.user_ekey = r.ekey 
  AND e.type = 't' 
  AND r.enroll_date < e.time
  AND NOT EXISTS (SELECT 1 FROM account_events e1
                  WHERE e1.user_ekey = r.ekey 
                    AND e1.type = 't' 
                    AND r.enroll_date < e1.time
                    AND e1.time < e.time)
  AND r.cid IS NULL;

该语句实际上并不等效:如果没有匹配的 account_events 行,您的语句会将 cid 更新为 NULL,而我的语句不会更新该行。