社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
昨天临近7点,手头的活干完了,心里美滋滋的。想着今天可以提前下班了,晚上回去干些什么呢。。。。。这时候,QQ弹出老大发我的消息:你上次写的JOB脚本中,出了点问题!当时第一反应就是,What?程序都运行得好好的,怎么会有问题呢!退一万步说,即使出现线上报错,也应该看到报错日志!(PS:作为一个立志要成为大神的开发工程师来说,怎么允许自己的线上代码出问题!)老大不说话,抛出了一个SQL语句:
看到这个语句, 第一反应,没啥问题啊!再仔细看,what,执行时间为啥这么慢???于是就有了今天的这篇文章。
首先说下这个JOB程序的背景:表里面存放着历年来的注册电话号码(当然是进行加密过了的!),现在需要对这些加密的电话号码先还原成真实的电话号码,然后用另外一套算法进行加密,目的是统一公司的电话号码加密方式,方便BI那边集中处理。其实吧,这个需求除了加密算法要重写(简单的说,就是阅读加密算法的JAVA实现版本,用PHP来实现)有点挑战性外,其它部分根本就没啥难度,主要做法就是:一次批量读取500-100条数据,然后用加密算法批量处理,然后插入到数据表里面即可,这个过程中,控制读写的频率即可(防止高频率大批量读写数据表对线上业务造成影响)!最后完成任务,测试OK,上线!在这里,查询表,主要使用语句
SELECT * FROM table LIMIT 500 offset rows
主要就是从"table"表中读取500条数据,偏移量是rows。在测试的时候,这样没啥问题,然后执行效果也挺好的。但是上线后,问题就来了:主要是,这个表里面的数据量实在是太多了
有5000多w条数据!我把老大发我的那个语句拿到表里面去执行了下:
执行时间竟然要2s多!我勒个去,这还只是百万级别,那如果到了千万级别呢?我尝试着在表里面执行了下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019030914355581.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3docTE5ODkwODI3,size_16,color_FFFFFF,t_70
差不多10s!要知道我有5000多w条数据要处理呢!如果按照10s来估算,差不多得5000000秒!(约58天)
作为一个要立志成为大神的人来说,这个问题不能容忍!于是停止线上JOB的运行,开始想办法解决这个问题。然后就发现,要解决这个问题其实很简单:表里面有id,利用id的自增方法来代代替limit offset的这种方式。在表里面尝试了下,按照相同的方式查询:
最后约为0.0053s!相差大概是2000倍的差距!问题找到了,解决方法也就随之而来!最后仅用了40多个小时JOB就处理完了所有的数据!PS:代码执行的效率在数据量小的时候,可能看不出来,但是当数据量或并发量很大的情况下,效率低的代码就容易成为性能瓶颈!看来,成为大神之路还很漫长啊!
总结如下:
优化前:
SELECT * FROM `table` WHERE id > 0 LIMIT 500 OFFSET 3057000;
优化后:
SELECT * FROM `table` WHERE id > 3057000 LIMIT 500
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!