利用insert select 替代update以提升性能,JoeyChou

利用insert select 替代update以提升性能

遇到一个sql运行很慢:
update tablea set cola = ( select sum(colb) from tableb where a.col1=b.col1);
其中tablea有1千万条记录,tableb有4千万条记录。update语句没有过滤条件,这意味着要对tablea表的1千万条记录都要遍历一遍,而且每一条都要查询4千万的表。这样的操作肯定会历经很长的时间并且消耗很多服务器的资源。实际运行了差不多10个小时,这是无法接受的。

考虑改写这个sql:

这个sql慢就慢在每个记录都要查询另一个表,要用别的方式避免这种处理。

第一步:先建一个临时表,与tablea的结构是完全一样的,这里注意要建成session级的临时表,使临时表的数据可以在session级保留。
create temporary table temp_a as select * from tablea where 1=2 on commit preserve rows;

第二步:这里假设tablea只有2个字段:cola 和 col1
insert into temp_a
select a.col1,b.sum_b
from tablea a,
(select col1,sum(colb) sum_b
from tableb
group by col1) b
where a.col1 = b.col1;

第三步:将tablea表truncate掉,然后将temp_a表的数据insert回来。
truncate table tablea;
insert into tablea select * from temp_a;

这样改写后,7分钟就运行完成了


以下是单表update select sum 的情况优化:

update t_user_count_opt b,(select userid as uid,sum(money_borrow) as bcount,sum(money_deposit) as bcount2 from t_user_borrow where status in(1,3) group by userid) c set b.money_borrow=c.bcount,b.money_deposit=c.bcount2 where b.user_id=c.uid;