索引原理
从底层看,如何选择表的主键?
推荐使用自增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只会选择一个索引,所以考虑联合索引
接下来删除这三个索引,建一个联合索引
再看执行计划
这样效率就很明显了。探索一下联合索引的最左原则
结论:a,b,c可以顺序无所谓,mysql会替你优化(具体情况具体分析,不是一定的)
a
a,b
a,c
b,c
结论:a,b,c这样的联合索引只要有a就能走索引
Like ‘%***’
Like ‘***%’
结论:Like ‘%***’不能命中索引。
补充一点:联合索引有的场景下可以解决排序的问题
结合测试结果,针对筛选条件很多的列表页,怎么做索引优化呢?
分析一下刚才的结论
第一:where条件后只能有一个索引被用到
第二:联合索引只要有最左边的字段就能走索引
第三:联合索引可以不要求where条件后面的字段有序(cba,ca)
现在再来设计一下:
最好找一个默认一定会查询的字段作为联合索引的a(最左),这样用户不选择条件又或者是选择查询条件,都会走联合索引。默认一定会查询的字段怎么找?例如用户的角色去筛选等等,这个就得具体业务具体分析了
覆盖索引
既然说到了联合索引那就顺带说一下覆盖索引。啥叫覆盖索引?就是你select的字段都是联合索引中的字段,比如有联合索引abc,那么”select a,b,c from table where a=’*’ and b =’*’ and c=’*’”这样的就是覆盖索引。
覆盖索引为什么效率很高?
从索引原理的索引树上来看,可以直接在索引文件的索引树上就能够取到所有需要查询的字段,那直接通过遍历索引取得了数据,不需要回表,减少了io操作,性能自然就提高了。
锁
Myisam:表锁(并发度不够)
Innodb:表锁,行锁
Sql优化为什么要说说锁?首先即使是行锁,要锁定某一行,获取锁和释放锁的过程也是复杂的,耗资源的,所以尽量别让一个事物锁住一大片。另外如果程序员写代码不规范也可能产生死锁。
怎么产生死锁?
首先表锁肯定是不会产生死锁了,锁住了整张表怎么还能产生死锁呢。但是如果是行锁,举个例子:
T1锁住table1的id=1行,等待table2的id=11行,T2锁table2的id=11,待table1的id=1行,相互等待
所以在系统业务繁忙的时候别去做大批量的update,会导致锁表,从而阻塞掉业务,导致超时。
JION
Join的原理是什么?
怎么看Join buffer的大小?
Showvariables like ‘join_%’
Order by
尽量去命中索引,为什么?
用到了文件排序
Using filesort没有了,因为索引已经替我们做了排序(叶子节点从左到右相互指向)
那么在没有索引的情况下,order by的排序是怎么样做的呢?
当你的buffer够大时,mysql会选择第二种排序方式,否则第一种,显然一次IO的效率好于两次,所以一定要什么字段就拿什么字段,千万别select * ,另外必要时可以增大buffer的大小
Group by
基于order by,先排序再分组
可以看到,也用到了索引,所以优化方式和order by一样
Distinct
基于group by
Limit
例子是针对自增id的
要查第7,8行会拿到我们表的9行
这样呢就只有3行
!=
用到了索引
。。。。还有很多,建议大家自己去尝试,别死记硬背,理解原理,另外数据库版本不同是否走索引的结果也不一定一样
写在最后
建议慢sql首先考虑人为因素,需求是否合理,表结构是否合理,sql设计是否合理,这件事情到底适不适合或者说应该还是不应该让关系型数据库去做。