首页 » 网站建设 » xml转phpweixn技巧_线上sql实行慢分享3个优化案例

xml转phpweixn技巧_线上sql实行慢分享3个优化案例

访客 2024-12-17 0

扫一扫用手机浏览

文章目录 [+]

vc_member_bak 表数据量在46万旁边,开启日志剖析后,创造是下面这条 sql 实行太慢导致

SELECT FROM vc_member WHERE qq_id = 'xxx' OR app_id = 'xxx' OR weixin_id = 'xxx' ;

实行结果:

xml转phpweixn技巧_线上sql实行慢分享3个优化案例

须要1.3秒旁边,这是在我本地仿照的数据,线上用户在百万级别,耗时已经达到2、3秒,于是博主开始上 explain,剖析 sql 实行

xml转phpweixn技巧_线上sql实行慢分享3个优化案例
(图片来自网络侵删)

由于 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 id="updateStockNum"> <foreach collection="stockNumDTOS" item="stockNumDTO"> 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; </foreach></update>

可以看出这个更新 sql 实质上便是在一条 sql 里实行了多个 update 语句。
这个写法虽然不是在代码 for 循环中实行,但是这条 sql 语句实行时,MySql 任然是单条单条实行的。
这里用 tb_newbee_mall_goods_info 表举例,表构造展示:

3个 update 语句同时实行结果如下:

如上,如果个中一个 update 语句须要耗时40毫秒,那么当有100条 update 语句时,接口耗时就会来到4秒,这显然是不可接管的。

那有没有一种高等一点的写法来实行 update 批量更新嘞?

当然是有的,博主后来利用了 update + case 语句完成这个批量更新功能,

update + casesql 如下:

UPDATE tb_newbee_mall_goods_info SET stock_num =CASEgoods_id WHEN 10003 THENstock_num - 1 WHEN 10004 THENstock_num - 1 WHEN 10005 THENstock_num - 1 ELSE stock_num END WHEREgoods_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创建 /@Testpublic void cdkCreate() { Integer num = 100000; List<CdkInfo> 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<CdkInfo> 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 /@Testpublic void asyncCdkCreate() { int num = 100000; List<CdkInfo> 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<Boolean> flagList = new ArrayList<>(); List<CompletableFuture<Void>> futures = new ArrayList<>(); for (List<CdkInfo> cdkInfos : ListUtil.partition(list, 1000)) { CompletableFuture<Void> 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个优化案例就先容完了,希望对大家日常开拓有所帮助,喜好的朋友们可以点赞加关注。

标签:

相关文章

php为无色透明技巧_水货钻石其实也还行

从各种钻石中,可以看到大大小小的“包裹体” 图片来源:参考文献包裹体的种类多样。比钻石形成更早的包裹体,叫“原生包裹体”;与钻石同...

网站建设 2024-12-19 阅读0 评论0

phpstudy发送gbk技巧_php的文件上传

这里首先声明一下这一章的内容比较多,比较难,你要抱着和自己去世磕的态度。细微之处不放过,多敲多练是王道。 学习就像爬山,得一步一步...

网站建设 2024-12-19 阅读0 评论0