动动手指,这段程序性能提升2s~15s

[复制链接]
发表于 2022-10-21 17:52:06 | 显示全部楼层 |阅读模式
性能优化说明:判断数据表里是否有数据,用limit 1/top 1取代求count
近期,数据中心系统负荷大,mysql服务器的CPU动辄高达90%以上。代码和数据表存在很大优化空间。
这里分享一个定时同步数据的Job任务的优化过程。
 
先上代码

 
  1. public void executeJob(String jobParameter) {
  2.     //获取风控个体工商业者信息表数据总计,如果没有任何数据,则需要初始化
  3.     int sohoCount = sbhSohoManager.count();
  4.     if (sohoCount == 0) {
  5.         // 首次同步数据
  6.         ...
  7.     } else {
  8.         // 非首次,增量同步数据
  9.         ...
  10.     }
  11. }
复制代码
 
 
从这段代码不难看出来,根据表的数据量来走不同的分支处理逻辑。
其中,sbhSohoManager#count是mybatisplus原生的count方法。对应SQL是: SELECT COUNT(1) FROM sbh_soho
查log,发现这么一个count,耗时竟然2s~15s。

 

 
 
 
优化方案

要实现这样一个判断,不用求count,取一条记录的耗时就小到数个ms了。对应的SQL是:SELECT * FROM sbh_soho limit 1

 
 
因此改一下逻辑。
  1. public void executeJob(String jobParameter) {
  2.     //获取风控个体工商业者信息表数据总计,如果没有任何数据,则需要初始化
  3.     int sohoCount = sbhSohoManager.hasRecord();
  4.     if (sohoCount == 0) {
  5.         // 首次同步数据
  6.         ...
  7.     } else {
  8.         // 非首次,增量同步数据
  9.         ...
  10.     }
  11. }
复制代码
 
其中,sbhSohoManager#hasRecord 巧用mybatisplus的QueryWrapper#last("limit 1")实现SQL里的limit,定义如下
  1.     /**
  2.      * 仅判断表里有没有数据
  3.      * @return
  4.      */
  5.     public boolean hasRecord(){
  6.         QueryWrapper<SbhSoho> objectQueryWrapper = new QueryWrapper<>();
  7.         objectQueryWrapper.last("limit 1");
  8.         SbhSoho sbhSoho =getOne(objectQueryWrapper); //baseMapper.selectOne( null);
  9.         return sbhSoho!=null;
  10.     }
复制代码
View Code 
还有优化空间

这是一个同步数据的job。定期从源库同步一个表的增量数据到当前库。
基于此,高端的程序员,你也许会想到, 判断是否存在数据其实不用每次查库。
所以,内存/缓存又派上用场了。————————————>另起一段。
当前JobService里定义一个static boolean 的field: isFirstTime,默认值为false。 job首次跑的时候.... 写伪代码吧,描述起来太费脑子费文字还不易懂。
  1. @Service
  2. public class SbhSohoSyncBizJobImpl {
  3.     private static boolean isFirstTime = true;
  4.    
  5.     public void executeJob(String jobParameter) {
  6.         if ( isFirstTime == true) {
  7.             isFirstTime = ! CacheUtil.getCache("onlyoncekey" + getClass().getSimpleName(), TimeUnit.DAYS.toSeconds(30), () -> sbhSohoManager.hasRecord());
  8.         }
  9.         //获取风控个体工商业者信息表数据总计,如果没有任何数据,则需要初始化
  10.         if (isFirstTime == true) {
  11.             // 首次同步数据
  12.             ...
  13.         } else {
  14.             // 非首次,增量同步数据
  15.             ...
  16.         }
  17.     }
  18. }
复制代码
 
CacheUtil.getCache是利用Redist#get、Redis#set、Supplier封装一个缓存util方法。
 


 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表