SQL慢查询优化方案详解
作者:摆烂的小趴菜
sql排查方式
首先,如何排查sql是否走了索引,通过explain关键字找出sql的执行计划,通过在对执行计划的分析,找出某表关联部分是否走了索引。
具体语法:
explain select * from table_name;
让不走索引的sql走索引
mysql有个特别神奇的东西叫做索引,一个sql走或不走索引,查询效率差别极大,因此大部分的查询效率问题都是不走索引造成的,也就意味着,只要找到不走索引的原因,就能解决大部分查询效率的问题。
因此专门开了一个文章罗列不走索引的情况,欢迎大家补充或指正。 不走索引的情况及一些规避方案
联合索引,避免回表
众所周知,联合索引的叶子节点存储了索引字段的值,因此,合理的设计联合索引,可以避免回表操作。
比如:我的表中有四十个字段,但是查询频率比较高的只有a,b,c三个字段,这时候,如果我想进一步提升效率,我可以将abc三个字段设计一个联合索引,查询的速度就会有进一步提升。
特殊优化,深度分页
深度分页: 指的是在分页查询的时候,页数标记的特别高(如查询第10000页的数据),这样,如果正常查询的sql会出现 select * from table_name limit 10000,10
的sql出现,会造成极大的性能问题。
因此深度分页问题需要有一定的优化。
- 方案一:从业务方面搞定,因为很多业务根本用不到那么多分页,那么就可以限制最大分页的页数,比如百度的最大显示页码就只有76页。
业务方面如果搞不定,只能通过技术手段搞定,那么我们就分析一下问题出在哪?
我们能够想到,性能瓶颈出在了limit页码过大的问题上,我们知道,索引的结构(B+树)有一个特性,就是叶子节点之间依靠双向链表连接,这个特性主要是针对范围查询做的优化,因此在进行分页查询的时候,我们会直接通过链表进行查询,问题就出在了这里,由于页码过大,而且查询字段过多,每次查询时候需要回表,所以链表在遍历的时候时间过长,造成了性能瓶颈。因此引申出了下面两个优化方案。
- 方案二:分页查询时将id作为查询条件传过来,然后往后查十条,这样可以先通过索引锁定到第一条数据,然后通过链表往后遍历十条数据,从而达到优化的效果。 如果你的已有的方案不是那么方便改,可以考虑下边的方案。
- 方案三:在sql中先分页查询到id(不需回表查询速度较快),然后在进行表关联进行分页查询,具体sql如下(类似):
select table.* from table_name as table inner join ( select id from table limit 3000000,10 ) as tmp on tmp.id=table.id;
突破瓶颈,分库分表
分库
每个数据库是有一个最大连接数的,超过这个连接数会查询超时,所以,在你的项目的并发量超过一定量级之后,你就需要考虑分库了,至于具体分多少个库,看实际QPS量有多少,一个库默认的连接数是100,按照具体QPS推算需要分出多少个库。
分表
分表又分为水平分表和垂直分表。
水平分表: 是将一张表的字段拆分到两张表上,从而达到单表数据存储量降低的目的。一般应用的场景都是按照业务含义拆分,可以拆分成多张一对一的表,各个表通过主键关联,比如将sku表拆分成sku基础信息表,sku扩展表,sku状态表,等等。
垂直分表: 是单表数据过多后,会导致数据查询时候读盘次数增加,从而查询效率降低,这时候就考虑将数据分到多张表上,通常做法是确定一个拆分键,将拆分键进行一定的算法(比如:hash运算后按照分表数取模),最终落到某张表中。
基本上单表量级超过两千万就可以考虑分表了,分多少表按照 最大量级除以500-1000万 左右数据计算。
至于为什么最大阈值是两千万,可以看下 mysql B+树 索引机制 及 InnoDB一棵B+树可以存放多少行数据? 深入了解一下。
削峰操作,临时缓存
有一种慢查询的情况是出在了一种峰值查询的时候,就是有时候会出现某个时间段有些业务几种出,但是定时任务过于集中,导致某一个短暂的时间段QPS暴增,从而数据库扛不住压力,出现了慢查询甚至于数据库崩溃,由于是峰值的问题,扩容机器又很浪费,不扩容又扛不住压力,为了避免这类问题,可以考虑引入缓存机制进行削峰操作,通过缓存机制短暂的保存数据库信息,让峰值的请求都压在缓存上,从而间接的避免了慢查询的情况。
当然,无论是使用缓存中间件Redis,或者内存中间件MemoryCache都可以解决这类问题。
以慢打快,异步处理
同样是慢查询出现定时任务批量处理数据的情况,但是定时任务过于集中,导致某一个短暂的时间段QPS暴增,这时候更好的方案是通过mq异步处理数据,通过控制mq的消费密度来减轻qps,从而达到减轻数据库的压力,以时间换空间,以慢打快,效果奇好。
更换思路,曲线救国
如果是在查询效率提升不上去,就考虑更换查询中间件吧,使用大数据的处理方式,比如,落ElasticSearch查询。
到此这篇关于SQL慢查询优化方案详解的文章就介绍到这了,更多相关SQL慢查询优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!