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语句有什么好的写法吗?
还是我该去考虑增加索引,或者做数据拆分了?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在没有遇到写锁队列之前,总觉得联表更新是极好的。现在总觉得,分拆SQL+缓存+异步是极好的。
在v2ex上看到有朋友说通过添加索引与使用临时表的方法,尝试了一下,效率确实有很大提高。
主要思路就是将数据从b表提取出来,存放到临时表c(字段为session,fail_reason)
然后通过 update a,c set a.fail_reason = c.fail_reason where a.session=b.session
几十万的数据也只要十几秒就更新完成。
谢谢楼上几位给出的思路:)
分拆sql。 复杂的sql,很容易导致数据库性能的急剧下降。可以考虑先查出当前一个小时内
a
表失败的, 通过脚本循环:每次查询一条sessionid
失败的原因,再更新到a
表, 然后再循环处理下一条。虽然看似不如一条大sql 来的简单, 但这样降低了数据库计算的复杂性和消耗, 很多时候会很好的提升效率优化复杂sql。 可以通过
explain
, 查看sql是否恰当的使用了索引, 同时应该尽量优先缩小结果集。建议题主分拆 sql吧, 看看能不能获得想要的性能