何为索引?
简单来说索引是一种数据结构,就像是一本书的目录,目的就是使mysql能够使用索引更快速的查询出数据,减少查询过程中扫描的数据行数。
索引类型
从大的方面来说索引可分为聚集索引(主键索引)和普通索引,当然有的书籍上也称之为聚簇索引和非聚簇索引,其实本质都一样,大家可以理解为除了主键索引其它的都是普通索引。
聚集索引和普通索引的区别
看到上面的图大家心里是不是就很清楚了,没错二者最大的区别在于对应的索引树结构中的叶子节点存储的数据不同,主键索引对应的索引树中视为叶子节点存储的是索引数据和行数据,而普通索引对应索引树的叶子节点中存储的是索引数据和对应的行主键,那在使用的时候会有什么不同的?这里会涉及到回表查询-当使用主键索引查询的时候,mysql只需要访问一次索引树就可以将需要的数据查询出来,而普通索引因为对应的索引树叶子点存储的是索引数据和对应的行主键,所以还需要根据获取的主键去主键索引树中将数据查询出来,这也就是二次回表查询,当数据量大的时候二者的查询的性能就会很明显的体现出来,难道普通索引就一定不能避免回表查询吗?答案是否定的,至于怎么避免往下接着看。
创建合适的索引
创建不合理的索引不仅仅不会提升查询性能,反而会占用存储空间,增加索引的维护成本,例如当数据量不大的时候,你可能认为先在某个列上创建索引,反正以后数据量会增大,这样也不能说错,长远考虑肯定是没错的,但是就当前而言完全没必要,数据量小的时候即便创建了索引mysql内置的优化器也不会使用-用不用索引优化器是基于成本来决定。
当sql语句中查询条件列不是单一的时候,没必要给每个列都创建单独的索引,可以使用组合索引代替。
创建组合索引的时候我们需要考虑索引中字段的顺序和选择性,尤其是字段的顺序如果考虑不周到会导致只能使用组合索引的一部分,至于原因会在下面给出。
索引优化
索引覆盖
索引覆盖是一种对索引的优化方法,可以避免使用索引时的发生的二次回表查询
至于为什么能避免大家看聚集索引和普通索引的区别就能得出答案,这种优化从另一方面也告诉我们平常写sql时候不要写 select * 因为没有任何一个索引可以覆盖全部字段列。
索引失效情况
1.使用模糊查询,这里所说的模糊查询是指 '%a%'或者 ‘%a’ 方式会导致索引失效
2.对索引字段进行类型转换
3.对索引字段进行运算
4.索引为表达式的一部分
5.使用or查询
6.where 后的第一个索引字段使用的范围查询,导致后面的字段无法使用索引,上面说的创建组合索引为什么要选择合适的字段顺序就是这个原因
7.使用带有in并且分页的子查询
当然这些都是常见的情况,还有一些例使用group by orde by 的时候如果查询的的数据量查过总数据量的30%也不会哈斯用索引(每个版本都不一样)
再或者sql优化器由于得到了不准群的却无信息,使得优化器放弃使用索引
总结:
这里只是介绍了sql优化中使用使用索引方式,当然还有其它方面的优化方式,例如将sql中的判断,分组,统计等逻辑下放到程序代码中实现,重写sql,对复杂sql进行拆分,使用查询缓存,将一些比较耗费时间的查询结果缓存起来等,如果表数据量特别大的时候使用索引的用处就不是很大了,这时候可能需要分区表或者直接分表。