mysql优化

索引原理


mysql优化_第1张图片
MYISAM


mysql优化_第2张图片
Innodb

从底层看,如何选择表的主键?

推荐使用自增ID,因为有序这样使每次新插入的对象都在树的子节点的最右侧,如果用例如UUID之类的,没有物理连续性,在树上无序的插入,分裂耗费资源,另外这种id很长,空间占有也比int大。

执行计划

解释几个比较重要的参数

Type:

sql查询优化中一个很重要的指标,结果值从好到坏依次是:


system> const > eq_ref > ref > fulltext > ref_or_null > index_merge> unique_subquery > index_subquery > range > index > ALL

key:

实际使用的索引

Key_len:

所使用的索引的长度,越短越好。为什么?看索引树,索引长了占空间。

Rows:

找到所需要的记录需要读取的行数,当然也越小越好

Extra:

注意两个:1,using filesort文件排序,无法用索引完成排序操作,需要优化

2.using

temporary 用到了临时表,会做数据的拷贝很耗费资源

联合索引

首先拿个sql分析一下执行计划,发现没有走索引,


mysql优化_第3张图片

然后看一下该表的索引结构


仅仅有新建表的时候自动建的主键索引,所以应该建索引,怎么建?先分别建,


mysql优化_第4张图片

再看看执行计划呢?


只使用了一个索引,

结论:这种情况下mysql只会选择一个索引,所以考虑联合索引


接下来删除这三个索引,建一个联合索引


mysql优化_第5张图片

再看执行计划


这样效率就很明显了。探索一下联合索引的最左原则


结论:a,b,c可以顺序无所谓,mysql会替你优化(具体情况具体分析,不是一定的)


a


a,b


a,c


b,c


结论:a,b,c这样的联合索引只要有a就能走索引


Like ‘%***’


Like ‘***%’

结论:Like ‘%***’不能命中索引。


补充一点:联合索引有的场景下可以解决排序的问题


mysql优化_第6张图片

结合测试结果,针对筛选条件很多的列表页,怎么做索引优化呢?

分析一下刚才的结论

第一:where条件后只能有一个索引被用到

第二:联合索引只要有最左边的字段就能走索引

第三:联合索引可以不要求where条件后面的字段有序(cba,ca)

现在再来设计一下:

最好找一个默认一定会查询的字段作为联合索引的a(最左),这样用户不选择条件又或者是选择查询条件,都会走联合索引。默认一定会查询的字段怎么找?例如用户的角色去筛选等等,这个就得具体业务具体分析了

覆盖索引

既然说到了联合索引那就顺带说一下覆盖索引。啥叫覆盖索引?就是你select的字段都是联合索引中的字段,比如有联合索引abc,那么”select a,b,c from table where a=’*’ and b =’*’ and c=’*’”这样的就是覆盖索引。

覆盖索引为什么效率很高?

从索引原理的索引树上来看,可以直接在索引文件的索引树上就能够取到所有需要查询的字段,那直接通过遍历索引取得了数据,不需要回表,减少了io操作,性能自然就提高了。


Myisam:表锁(并发度不够)

Innodb:表锁,行锁

Sql优化为什么要说说锁?首先即使是行锁,要锁定某一行,获取锁和释放锁的过程也是复杂的,耗资源的,所以尽量别让一个事物锁住一大片。另外如果程序员写代码不规范也可能产生死锁。

怎么产生死锁?

首先表锁肯定是不会产生死锁了,锁住了整张表怎么还能产生死锁呢。但是如果是行锁,举个例子:


mysql优化_第7张图片

T1锁住table1的id=1行,等待table2的id=11行,T2锁table2的id=11,待table1的id=1行,相互等待


所以在系统业务繁忙的时候别去做大批量的update,会导致锁表,从而阻塞掉业务,导致超时。

JION

Join的原理是什么?


mysql优化_第8张图片

怎么看Join buffer的大小?

Showvariables like ‘join_%’


Order by

尽量去命中索引,为什么?


mysql优化_第9张图片

用到了文件排序


mysql优化_第10张图片

Using filesort没有了,因为索引已经替我们做了排序(叶子节点从左到右相互指向)


那么在没有索引的情况下,order by的排序是怎么样做的呢?


mysql优化_第11张图片

当你的buffer够大时,mysql会选择第二种排序方式,否则第一种,显然一次IO的效率好于两次,所以一定要什么字段就拿什么字段,千万别select * ,另外必要时可以增大buffer的大小


Group by

基于order by,先排序再分组


mysql优化_第12张图片

可以看到,也用到了索引,所以优化方式和order by一样

Distinct

基于group by


Limit


mysql优化_第13张图片

例子是针对自增id的

要查第7,8行会拿到我们表的9行


mysql优化_第14张图片

这样呢就只有3行


=


mysql优化_第15张图片

用到了索引




。。。。还有很多,建议大家自己去尝试,别死记硬背,理解原理,另外数据库版本不同是否走索引的结果也不一定一样

写在最后

建议慢sql首先考虑人为因素,需求是否合理,表结构是否合理,sql设计是否合理,这件事情到底适不适合或者说应该还是不应该让关系型数据库去做。

你可能感兴趣的:(mysql优化)