数据层
对于慢查询,应首先考虑从数据层做原因分析,理由很简单
1.数据层的接口一般来说除了通用的都是单一职责的,耦合性低,易于修改
2.效果立杆见影,做出任何修改之后,在数据库中都能快速得到结果
原因分析
<1>是否满足基本的索引原则
索引匹配,索引覆盖等原则
<2>覆盖索引
查询结果是否都存在于索引之中,可以有效减少回表,提高查询速度
业务层
原因分析
1.是否存在循环查询
对于已经完成了数据层优化仍然不满足性能的非并发对外接口可以考虑多线程循环调用数据库查询
虽然mysql拥有线程池,但是对于业务层普通的foreach循环来说,你这里是阻塞的,你的每条查询都必须等待上一条查询结束,但这种策略仅用于如后台管理页面某种统计接口,原因后述 原文中使用多线程调用,并且要获取返回值,java中使用CompleteFuture类并创建线程池,但是这里存在很多问题,由于是共享线程池,如果你这个接口并发量本来就很高,你这里用此方法能提高单个查询的效率,却会让其他的线程全部等待,反而降低了总体的速度 如果是我会在这里考虑使用stream流去操作
2.是否存在远程调用
这种在查询接口中存在的远程调用一般来说都是为了同步某种数据,这种远程调用不仅会导致查询慢,还会出现各种各样的问题,常见的健壮性不够都是给后面埋坑,远程调用还是
1.推荐专接口专用不做增强以外的任何耦合功能
2.尽量用于定时任务
当然,针对已经写好的代码那没办法
<1>同步时效性要求不严格
比如可以允许5分钟或者10分钟的延迟
<2>项目业务流程易于且可更改
大多数代码由在职人员编写,可以很方便的更改业务流程,毕竟你这里需要同步,其他地方也需要同步,每个都去临时远程调用,对面系统给你查也是需要时间的,在某种意义上在对面系统中类似于上文中的循环查询
注:
由于以上知识毫无体系浅薄,仅用于面试思路,实际开发中,本人遇到的除了索引优化,其他的方法基本没用,比如远程调用,首先是要满足产品的需求,要求必须及时,这怎么优化呢?接口就这一个,对方也不提供批量接口,你要不然只能通过stream去操作。然后是改流程或者新增表存储,可能就给你一上午的时间,优化下sql就完事了,你还想写一套新的或者增加一个表来存数据改变流程,这不是给自己挖坑吗?这个流程后面都是由你负责,以前和他有关你有完整的了解过吗,当时作者为什么这样写?你怎么能保证自己比第一个写得牛逼呢?这就像一座屎山,如果是耦合度极低的还可以稍微改改,这种涉及到流程,涉及到新的一套的,不仅可能出现各种问题,还会给后面的人优化带来困难,如果你不是这个项目的负责人你就别搞这些东西。
# 从20s优化到500ms,我用了这三招 感谢文章后面的各种大佬评论的补充,作者属于是抛砖引玉了,后面的评论解答了我为什么从来没有在我遇到的代码中看到利用线程池优化数据库查询的案例