首页 > mysql从一张表更新另一张表,如何效率最高?

mysql从一张表更新另一张表,如何效率最高?

最近工作上遇到的问题,有条sql语句执行时间一直很长,情况如下:
a表记录电话通话情况的表,b表记录的是电话通话失败的原因,两表之间通过一个叫sessionid的字段关联在一起。两表结构大致如下:

## a 表:##
===========
id, 主键,自增
caller --> 主叫号码
callee --> 被叫号码
state  --> 通话结果,成功=1,失败=2
sessionid --> 唯一标志一通电话的标记位
fail_reason --> 电话通话失败原因
send_time --> 电话拨号的时间,unix时间戳

------------------------------------

## b 表:##
===========
id --> 主键,自增id
reason  --> 电话通话失败的原因
sessionid --> 唯一标志一通电话的标记位
create_time --> 记录创建时间

a表记录大概50W条,b表记录大概20w条,且b表中存在sessionid重复的记录
由于某些原因,a失败原因字段不能关联b表查询得到,而要定期(30分钟或1个小时)从b表更新过来,这个更新语句该如何写效率最高?
最初我的写法是这样:

update a表 t 
============
set t.fail_reason  =  (SELECT t2.reason from   b表 t2 
        where t.sessionid = t2.sessionid 
        and t.status = 2 
        order by t2.create_time desc 
        limit 0,1
        )
where t.status = 2 
and UNIX_TIMESTAMP() -t.send_time < 3600 
and (t.fail_reason = '' or t.fail_reason is null)

以上语句写成数据库事件,每隔半个小时执行一次,后期随着数据增大,感觉效率非常低,执行一次最少都几十分钟,
后来百度google到另一种写法:

update a表 t ,b表 t2
=====================
set t.fail_reason=t2.reason
where t.sessionid=t2.sessionid
and t.status=2
and UNIX_TIMESTAMP() -t.send_time < 3600 
and (t.fail_reason = '' or t.fail_reason is null)

但还是很慢

请问这类逻辑,mysql中sql语句有什么好的写法吗?
还是我该去考虑增加索引,或者做数据拆分了?


在没有遇到写锁队列之前,总觉得联表更新是极好的。现在总觉得,分拆SQL+缓存+异步是极好的。


  1. 分拆sql。 复杂的sql,很容易导致数据库性能的急剧下降。可以考虑先查出当前一个小时内a表失败的, 通过脚本循环:每次查询一条sessionid失败的原因,再更新到a表, 然后再循环处理下一条。虽然看似不如一条大sql 来的简单, 但这样降低了数据库计算的复杂性和消耗, 很多时候会很好的提升效率

  2. 优化复杂sql。 可以通过explain, 查看sql是否恰当的使用了索引, 同时应该尽量优先缩小结果集。

建议题主分拆 sql吧, 看看能不能获得想要的性能


在v2ex上看到有朋友说通过添加索引与使用临时表的方法,尝试了一下,效率确实有很大提高。
主要思路就是将数据从b表提取出来,存放到临时表c(字段为session,fail_reason)
然后通过 update a,c set a.fail_reason = c.fail_reason where a.session=b.session
几十万的数据也只要十几秒就更新完成。
谢谢楼上几位给出的思路:)

【热门文章】
【热门文章】