范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

线上sql执行慢,分享3个优化案例

  前段时间,博主线上项目的几个后端接口执行耗时达到了三、四秒钟以上,查看接口代码,发现 sql 语句执行过慢,于是开始分析 sql 执行 这里把比较经典的优化案例分享给大家。  本文所讲述 MySql 8.0+ 代码演示地址:https://github.com/wayn111/newbee-mall-pro 博主github地址:github.com/wayn111 欢迎大家关注,点个star 一、or 查询条件错误
  线上有一个第三方账户扫码绑定手机号登录的接口,这个接口正常逻辑如下:  使用 苹果、QQ、微信获取扫描客户端登录二维码,获取用户第三方账户唯一ID后。 判断第三方账户ID是否存在用户表中,存在且已绑定手机号则直接返回用户 token 进行登录操作。 不存在则提示用户进行绑定手机号操作。 用户填写手机号及短信验证码后,进行第三方账户唯一ID与手机号的绑定,成功则返回用户 token 进行登录操作。
  博主记得这个接口是在21年10月上线的,到现在经历了一年多,接口执行时间是越来越慢,初步分析是用户数量持续增长,用户表记录越来越多,导致 sql 查询执行效率越来越低导致。这里用 vc_member_bak 进行举例,表结构以及数据展示,其中  apple_id、weixn_id、qq_id  有建立索引
  vc_member_bak 表数据量在46万左右,开启日志分析后,发现是下面这条 sql 执行太慢导致  SELECT * FROM vc_member  WHERE qq_id = "xxx" OR app_id = "xxx" OR weixin_id = "xxx" ;
  执行结果:
  需要1.3秒左右,这是在我本地模拟的数据,线上用户在百万级别,耗时已经达到2、3秒,于是博主开始上 explain,分析 sql 执行
  由于 explain 结果中 key 列为空,明显可知虽然 possible_keys 列有值,但是执行过程中,没有使用索引导致全表查询,从rows 列为46万可以看出已经基本接近于全表查询。
  那么问题出在哪里?我们不是已经给  apple_id、weixn_id、qq_id  三个字段都添加索引了吗。
  于是博主仔细查询 sql 语句发现里面有坑,查询的 where 条件上使用的三个条件字段是分别是  app_id、weixin_id、qq_id ,而我们的索引字段是 apple_id、weixn_id、qq_id ,很明显这是查询字段 apple_id 写成 app_id 了导致。app_id 没有加索引,所以在 or 条件查询下执行的就是全表扫描。
  更改字段后执行结果:
  Ok,这里发现了是查询字段写错了,那么修改查询字段正确后,查询0.18秒就正常了。  二、update 批量更新优化
  博主以前线上项目( Spring Boot + Mybatis )有一个接口需要批量更新库存,当时博主本着不能再代码 for 循环中执行更新逻辑的初衷,决定再 xml 文件中使用 foreach 标签执行批量更新逻辑,展示如下:               update tb_newbee_mall_goods_info          set stock_num = stock_num-#{stockNumDTO.goodsCount}         where goods_id = #{stockNumDTO.goodsId}          and stock_num>=#{stockNumDTO.goodsCount}          and goods_sell_status = 0;      
  可以看出这个更新 sql 本质上就是在一条 sql 里执行了多个 update 语句。这个写法虽然不是在代码 for 循环中执行,但是这条 sql 语句执行时,MySql 任然是单条单条执行的。这里用 tb_newbee_mall_goods_info 表举例,表结构展示:
  3个 update 语句同时执行结果如下:
  如上,假如其中一个 update 语句需要耗时40毫秒,那么当有100条 update 语句时,接口耗时就会来到4秒,这显然是不可接受的。
  那有没有一种高级一点的写法来执行 update 批量更新嘞?
  当然是有的,博主后来使用了  update + case  语句完成这个批量更新功能,
  update + case sql 如下: UPDATE tb_newbee_mall_goods_info  SET stock_num = CASE 		goods_id  		WHEN 10003 THEN 		stock_num - 1  		WHEN 10004 THEN 		stock_num - 1  		WHEN 10005 THEN 		stock_num - 1  		ELSE stock_num  END  WHERE 	goods_id IN ( 		10003, 		10004, 	10005  	)
  我们通过  SET stock_num = case goods_id when 10004 then stock_num - 1 ... ELSE stock_num END  条件,可以将对应 goods_id 的记录的库存数量设置成我们想要的结果。
  PS:需要注意的就是  case when then 语句不匹配时会返回 null,那就会造成不匹配的库存更新为 null。所以 ELSE stock_num END 条件一定要带上,当不匹配 case when then 条件时,将库存数量设置成原本数量。where 条件在这里其实可以不加,它起到的作用是限制更新范围,但是建议还是要加上,避免 sql 写错时,造成脏数据范围过大。
  update + case 执行结果:
  可以看出我们更新了3条记录,耗时50毫秒,更新记录越多时,优化效果也就明显。  三、多线程优化大批量数据插入速度
  博主线上有一个 cdk 兑换码业务,运营在后台创建一批 cdk 码时,系统会将这批码插入数据库中保存,这样可以保证用户兑换 cdk 时,码在数据库存在才能兑换,保障安全性。当运营创建十万条cdk记录时,线上耗时达到了十几秒。这里用 cdk_info 表举例,表结构展示:
  假如我们现在需要保存十万条 cdk_info 记录,分批次保存代码如下:  /**  * cdk创建  */ @Test public void cdkCreate() {     Integer num = 100000;     List list = new ArrayList<>(num);     Date date = new Date();     String createUser = "test";     for (Integer i = 0; i < num; i++) {         CdkInfo temp = new CdkInfo();         temp.setCdkNo(String.valueOf(i));         temp.setCreateTime(date);         temp.setCreateUser(createUser);         list.add(temp);     }     long begin = System.currentTimeMillis();     boolean flag = false;     for (List cdkInfos : ListUtil.partition(list, 1000)) {         flag = cdkInfoService.saveBatch(cdkInfos, cdkInfos.size());         if (!flag) {             break;         }     }     long end = System.currentTimeMillis();     log.info("执行耗时:" + (end - begin) + "ms");     Assert.isTrue(flag, "批量更新失败"); }
  执行耗时:
  可以看到在单一线程下,插入十万条记录差不多需要15秒了,这十万条数据之间没有关联,互不影响,那我们可以通过线程池提交单一批次的保存任务,配合  CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join()  方法,等所有任务执行完成拿到结果。代码如下: /**  * 通过线程池创建cdk  */ @Test public void asyncCdkCreate() {     int num = 100000;     List list = new ArrayList<>(num);     Date date = new Date();     String createUser = "test";     for (Integer i = 0; i < num; i++) {         CdkInfo temp = new CdkInfo();         temp.setCdkNo(String.valueOf(i));         temp.setCreateTime(date);         temp.setCreateUser(createUser);         list.add(temp);     }     long begin = System.currentTimeMillis();     List flagList = new ArrayList<>();     List> futures = new ArrayList<>();     for (List cdkInfos : ListUtil.partition(list, 1000)) {         CompletableFuture future = CompletableFuture.runAsync(() -> {             boolean b = cdkInfoService.saveBatch(cdkInfos, cdkInfos.size());             flagList.add(b);         }, ForkJoinPool.commonPool());         futures.add(future);     }     CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();     long end = System.currentTimeMillis();     log.info("执行耗时:" + (end - begin) + "ms");     Assert.isTrue(flagList.stream().filter(aBoolean -> !aBoolean).findFirst().orElse(true), "批量更新失败"); }
  执行耗时:
  可以看到执行耗时2.5秒,执行时间缩短了6倍。  总结
  到这里,本文所分享的3个优化案例就介绍完了,希望对大家日常开发有所帮助,喜欢的朋友们可以点赞加关注。

工业PON5G融合组网工厂内网络可以细分为企业内网和运营商网络。企业内网可以部署下沉UPFMEC,起到业务分流降低时延数据不出厂的作用。办公类数据可以经城域网进入运营商外网。企业内的5G无线部署可以多种中信银行新发放贷款利率年初已现触底迹象,按揭信贷需求在逐渐恢复中信银行行长方合英在3月24日举行的中信银行(601998。SH00998。HK)2022年业绩发布会上,中信银行行长方合英表示,今年的信贷投放计划大概是3500亿元到4000亿元探寻东林党前世今生(下)东林在宋元明清民各时代的消长上接前文南宋年间,因为北方沦陷,所以北地的商路先后被金元两朝垄断,南宋小朝廷不得不另辟商路,由此开启了下南洋的贸易(其实在此之前便已有海外贸易,只不过南宋时代的规模成几何倍增长,相全网最快的来华旅游签证顺利通过啦!ThefastesttouristvisatoChinainthewholenetworkpassedsmoothly!Beishitunmadeanurgentreservati袁庆今天打扮的像新娘子一样和大衣哥演出了今天,3月26日,美女袁庆应邀来单县演出,上午8时袁庆早早来到现场,看袁庆这打扮,发型时髦,怎么形容呢?象贵妃,还是昭君?不管怎么说,可以列为中国第五大美女!再看衣服,黑衣红裙,强从郭晶晶章泽天杨洋的身上,我看到了上流社会的轻视文白面书誏编辑白面书誏昨晚宝格丽盛典上,身穿黑色深V条纹礼服的刘亦菲,无疑是最亮眼存在。同参加的女明星张嘉倪与佟丽娅在其身旁都显得逊色几分。所以当晚的刘亦菲也是绝对的C位女王,成为沣西文教园一小聚焦课标理念创新优质课堂阳光讯(尚婉婷记者刘杰)为扎实推进双减工作,深入落实新课标理念,全面提高教师的课堂教学水平,打造优质课堂,促进学生学科素养不断提升,西咸新区沣西新城文教园第一小学首届创新课堂比赛第网飞挑战P站,这回赢麻了众所周知,网飞一向爱拍黄暴剧。有些尺度,甚至超过了曾经的黄暴霸主HBO。但,有一个对手,是网飞望尘莫及的。它就是鼎鼎大名的P站。论尺度,根本不在一个次元。有意思的是,网飞这次整了新徐州市贾汪区服务农民工暖心又温情中工网讯据江苏工人报消息,为切实做好农民工的维权服务工作,江苏省徐州市贾汪区总工会精心开展春暖农民工服务行动,暖心又温情。春风行动送岗位。区总工会联合区人社局等单位,采取线上推送线紫金e评让乡村人才出圈又出彩近日,求是杂志发表习近平总书记重要文章加快建设农业强国推进农业农村现代化,指出通过多方面努力,着力打造一支沉得下留得住能管用的乡村人才队伍,强化全面推进乡村振兴加快建设农业强国的智摊牌了!8000多亿美债或打水漂?耶伦拒绝优先偿还中国债务?在阅读此文前,诚邀您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持。文承爱编辑大宇我们经常看到很多媒体表示美方的经济出现了严重的衰退,美元的霸权地位正
中国人在俄罗斯建大棚,挡住了当地社会大哥的财路,他会有危险吗头条创作挑战赛阅读摘要丨安徽淮北人赵耀祖,在俄罗斯建蔬菜大棚,蔬菜一上市,立即占领了当地的市场,但是,他这样就把原来蔬菜经销商的财路给断了,那个经销商在当地还有一定势力,是一个社会归路结局归晓带着孩子与路晨补办婚礼,段柔和秦明宇好上了路晨问归晓行吗,归晓羞涩地嗯了一声,这恋人间亲热的场景下文是箭在弦上,却引而不发,并没有圆房。归路归晓是愿意把自己完全交给路晨的,因为担心再错过路晨却只是和归晓激情亲吻,肌肤接触,无锡360度美女部长余敏燕,号称南邮校花,靠大老虎上位腐败自古至今都是社会毒瘤,如果任凭腐败问题愈演愈烈,百姓必将苦不堪言。那些表面人前衣冠楚楚,满口仁义道德,为人民服务的高官。背地里过着挥金如土奢侈的生活,暗地里搞着权钱色的交易,却百度正式发布文心一言李彦宏十月怀胎一朝分娩百度正式发布文心一言李彦宏十月怀胎一朝分娩科创板日报16日讯,被称为中国版ChatGPT的百度文心一言,今日1400在百度北京总部大楼正式发布,百度同时在上海张江人工智能岛百度飞桨甲流凶猛!防毒光盾能否终结传染?光疫苗,带来免疫空间新时代。1hr甲流凶猛来袭一场甲流潮,正在这个春天飞速蔓延。笔者关注到这个事件是在2月份,北京市疾控中心发布的疫情周报显示,流感报告病例数位于首位这是今年来,新西安网评一年植计在于春,植此青绿泽后人春暖花开时,一起来履植。自2000年以来,全球新增绿化面积中约14来自中国2022年我国完成造林5745万亩目前天然林商业性采伐已由停伐减产到全面停止。屏幕前的你,欢迎通过线下植树租个女友应付催婚,高峰期2500元天!钱到位干什么都行?这届年轻人为了应对家里催婚有多拼?甚至催生了一个新行业女友出租。近些年来,租友产业发展得如火如荼。在各大网站和平台,都看得到租客们的踪迹。甚至在线下街头,也出现了举牌寻假女友回家过晨意帮忙丨我想过一个真实的生日!湘妹子全网寻找亲生父母从小,衡阳县演陂镇的仇新塘(化名)就知道自己是被养父母收养的。虽然生活的每一步都很艰难,但养父母对她很好。如今养父已去世十多年,养母也近90岁,还是一如既往地关心她。现在,仇新塘找各民族守望相助,结对子追梦伴飞大有学问各民族守望相助,结对子追梦伴飞(以下简称伴飞活动)是我们学校的品牌特色教育活动之一,2021年荣获全国民族团结进步创建创新案例。近日该活动又一次启动。来自少数民族预科部高教黑龙江将实行新高考!12种科目组合可别随便选,仔细看2024年黑龙江省将实行新高考,对于高一学生来说,这学期各科的成绩直接影响到高二选科方向。那么在总分750分中占至关重要位置的1该怎么选?选考科目等级赋分咋回事?12种组合到底该如小农机上山岗央视网消息(新闻联播)眼下,全国由南向北进入春耕大忙时节。在我国,丘陵山区耕地面积占到了全国的三分之一,也是保障粮食产量的重要来源。如何把这些分布零散耕作不易的土地利用起来?来看记