简介
索引是存储引擎用于快速定位记录的数据结构, 索引的优化对于性能优化是最有效的手段,良好的索引会让数据库的查询性能得到成百倍甚至千倍的提升,不好的索引也会导致数据库查询效率急剧下降。我们应该学会如何正确使用索引,来优化我们的查询,提高对索引的认知,避免MySQL 索引的误区。
下面主要分索引类型、索引策略、索引使用的原则与经验来介绍MySQL索引。
##索引类型
Normal 普通索引
最常见的索引, 一般都用此索引.
Unique 唯一索引
需保证此索引对应的数据没有重复项,可以用此项来保证一些约束条件,防止重复数据
###Full Text 全文索引
FULLTEXT 用于搜索很长一篇文章的时候,效果最好。但总体来讲,效率肯定不高, 使用的时候需要用分词工具,来转换成全文索引支持的格式方可正常使用,用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
索引方法
B-Tree
B tree 索引是我们最常见,最常用的索引,在InnoDb 里,它的实际实现是基于B+ Tree的。
B-tree 索引可以用于范围取值,精确匹配, JOIN, GROUP BY, ORDER BY, 应用范围非常广泛, 下面是一些例子:
全值匹配 如匹配 username, email
匹配列前缀 如匹配email 的 @前面的部分
匹配范围值 匹配数字类型, 日期类型, 比如 user.age between 12 and 20
精确匹配某一列并者范围匹配另外一列 如 user.name =‘John’ AND user.age between 12 and 20
Hash
Hash索引,基于Hash表实现,只有精确匹配所有列的查询才有效
实现:基于Hash 表实现,对所索引的列计算hash值,并索引。
优点: 结构紧凑,对于精确匹配所有列的查询,非常高效。
缺点:只能精确匹配所有列的值, 部分类型不适用于范围查找, Order By等, 应用范围比较窄。
INNODB 是不支持不是unique 的字段上加 Hash索引的。实测,如果类型是Normal 把type 改成Hash 是没用的
索引可以大大减少服务器所需要扫描的数据数量,帮助服务器避免排序和临时表,将随机IO变成顺序IO但索引不是万能的解决方案,不是越多越好,不恰当的索引会引起性能的下降,对于数据量表的小不如全表扫描好
索引策略
单列索引
单列索引是指在某一个列上建立的索引,是最常见的一种索引,一般用在一些区分性比较大的列上,比如username, 某个关联的ID
### 联合索引
联合索引是在多个列上一起建立的索引, 也是我们常见的一种索引,当有多个索引做相交的时候,通常意味着需要一个联合索引,而不是每列都建立一个索引。
但联合索引的作用范围尤其要注意,下图是一个基本的说明
下图是一个实际使用的例子
聚簇索引
聚簇索引不是一种索引类型,而是一种数据存储方式。InnoDb 的实现是在一个数据结构中保存了B-tree 索引与数据行。
在使用得当的情况下可以大大提高SELECT效率,但也有很大的弊端, 一张表只能有一个聚簇索引, 聚簇索引不应该包含经常修改的列
候选列: 主键,JOIN的列, 不常修改的列 GROUP BY 与ORDER BY 中用的列
语法:
CREATE CLUSTER INDEX xxxx
覆盖索引
覆盖索引不是一种索引,而是一种索引建立的方式。简单的来说, 你需要查的数据都在,索引所在的列内, 这样就是覆盖索引。索引的条目数,往往远小于数据行数,如果只读取索引不读取数据行,会极大的提高性能, 因为索引是按照顺序排列的,所以IO消费会少的多,以下情况覆盖索引有可能无法起作用:
- 没有任何索引能够覆盖这个查询
- 语句中有用了 LIKE 之类的操作
下面则是一个使用覆盖索引的例子, 注意Extra字段里面会不一样
原则与经验
- 不能一味的乱建索引,索引与查询优化相结合
- 索引要尽量找选择性比较高的列
- 避免无用索引与重复索引
- 索引应建立在经常被查询的列上
- 可预期的小型表不应建立索引
- 避免选择大型数据类型的列做为索引
- 要在经常用作过滤器的列上建索引
- 在经常Group By Order By JOIN 的列上建索引