慢查询优化方案
如果你的项目中出现了一些查询超时情况,很可能是项目中有了一些慢查询的情况产生,下面就慢查询的排查和解决方案进行一番分析。
sql排查方式
首先,如何排查sql是否走了索引,通过explain关键字找出sql的执行计划,通过在对执行计划的分析,找出某表关联部分是否走了索引。
具体语法:
explain select * from table_name;
具体执行计划的指标含义,详见:Sql执行计划的一些指标含义
让不走索引的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都可以解决这类问题。
更换思路,曲线救国
如果是在查询效率提升不上去,就考虑更换查询中间件吧,使用大数据的处理方式,比如,落ElasticSearch查询。
上一篇: MySQL规范