面试官:查询MySQL数据库慢怎么办?
性能优化问题,不论在面试还是平时工作中都会经常遇到。那么,我们要想顺利并快速的解决这类问题,就必须总结出自己的方法论。
从客户端发出请求,到服务端接收请求并处理,然后返回给客户端,我们可以把这个过程看成一个时间轴,如下图:
所以,优化的思路,就可以从客户端处理、网络传输、服务端处理这三个方面进行考虑。
一、客户端处理阶段:
1、不论是发起请求,还是接收响应结果,都需要消耗一定的资源,那么最好的解决方案就不要发出请求,比如:可以建立本地缓存。(当然,在大多数互联网分布式场景,由于本地缓存难以保证数据一致性,所以一般会借助第三方缓存如redis)
2、不论是发起请求,还是接收响应结果,都需要建立网络连接,那么最好的解决方案就是不要建立新的链接,比如:链接池。这样可以有效的减少资源消耗
3、代码层面进行优化,减少不必要的计算
4、系统架构层面优化,尽量减弱并发调用
二、网络传输阶段:
1、任何网络传输,都需要消耗一定的网络资源,那么在分布式场景中又避免不了网络传输,因此最好的解决方案就是对数据进行压缩处理,尽量减少网络资源消耗
2、当一次传输的数据量特别大时,可以考虑对数据进行分片、分批传输;当一次传输的数据量特别小时,可以考虑把多条数据进行打包合并,然后进行统一传输
3、虽然压缩数据,确实能有效减少网络资源消耗,但是由于互联网分布式高并发的场景较多,资源竞争激烈,所以我们很多时候不得不购买更多的网络资源,如:增加网络带宽、使用万兆网卡等
三、服务端处理阶段:
1、从软件层面进行优化
a.代码层面进行优化,减少不必要的计算
b.合理配置系统参数
c.合理设计软件系统架构
d.调整资源使用策略
2、从硬件层面优化
a.提高CPU核心数、主频、缓存
b.增大内存容量、读写速率
c.增大磁盘容量、提升磁盘读写速率(SSD)
那么接下来,小编就通过自己的方法论对“查询数据库慢”这个问题,进行一个全面分析:
一、客户端(应用APP)处理阶段:
1、添加redis缓存,减少查询数据库的频次
2、合理配置数据库连接池资源,比如,配置合理的最大连接数:最大连接数=CPU核心数*2+1(这是个经验值,可以根据压测结果自行调整)
3、使用性能较好的连接池框架,如Hikari(据说,Hikari是目前Java平台最快的链接池,性能对比:Hikari>Druid>c3p0)
4、从sql语句层级面进行优化,让sql执行更快(本文暂时不做sql调优方面的详述,只从宏观角度进行概述)
5、从系统架构层面优化,尽量减弱并发调用,比如:在某些特定场景,可以把某一段时间内实时执行的sql语句,通过定时任务进行批量执行
二、网络传输(与数据库交互)阶段:
1、关于压缩:MySQL有自己的序列化传输协议(我们一般不会进行改造或自研)
2、关于数据分片或打包:可以从sql语句层面进行优化,如:MySQL批处理
3、购买更多的网络资源,如:增加网络带宽、使用万兆网卡等
三、服务端(MySQL数据库)处理阶段:
1、从软件层面进行优化
a.代码层面进行优化(MySQL已自带optimizer优化器组件,会对我们发出的sql进行优化)
b.合理配置系统参数,如:索引优化、表结构优化、存储引擎优化等
c.合理设计软件系统架构,如:主从架构、PXC/MGC、MGR、ArkDB、TiDB等架构方案
d.调整资源使用策略,如:根据物理内存大小,适当增加MySQL缓存、集群扩容等
2、从硬件层面优化
a.提高CPU核心数、主频、缓存
b.增大内存容量、读写速率
c.增大磁盘容量、提升磁盘读写速率(SSD)
到这里,一定有不少同学会想:应该没有其他办法了吧……别急,接下来,才是真正的彩蛋~~~
其实,我们可以从上帝视角出发,站到更高层面思考这个问题:既然MySQL数据库查询效率慢,那么是否可以从业务维度,对我们的系统架构进行改造,比如某些场景,可以不用MySQL,改为搜索引擎Elasticsearch、Solandra(Solandra 是一个实时的分布式搜索引擎,基于Solr 和 Cassandra 构建)或者大数据存储Hbase等。
写在最后:
没有最好的方法论,只有更好的方法论。非常感谢大家的阅读,希望和大家互相交流互相学习,共同进步!!!