# MySQL系列 - 创建高性能索引

索引的分类

索引分为B-Tree索引、哈希索引、空间索引、全文索引、其他等索引。

在 MySQL 中,最常用的是 B-Tree 索引(也就是我们常说的B+树索引,这里B-Tree索引只是一个分类)

索引的优点

  • 索引大大减少了服务器需要扫描的数据量

  • 索引可以帮助服务器避免排序和临时表

  • 索引可以将随机I/O变成顺序I/O

创建高性能索引

下面根据不同的情况来说明,如何创建合适并且高性能的索引来提高索引效率。

  • 独立的列

如果查询中的列不是独立的,则 MySQL不会使用索引。

所谓独立的列指的是,查询中的列不能是表达式的一部分,要是独立的,举例如下

select * from t_user where id + 1 = 9;

在上面的查询语句,查询中的列 id 不是独立的,而是表达式 id + 1 的一部分,因此索引不会生效

关于索引失效的各种情况,详情参考 MySQL索引失效总结

  • 前缀索引

有时候需要很长的字符列,这会让索引变得大且慢。

我们可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。

当然,选择的部分字符不合适会导致过滤效果很差,所以一定要选择区分度较高的前缀建立索引。

创建前缀索引脚本如下:

alter table t_user add key (address(10));

该脚本表示以地址的前10个字符创建索引。

  • 多列索引

很多人对多列索引理解不够,为多个列创建独立的索引,或者按照错误的顺序创建多列索引。

在多个列上建立独立的索引,一般情况下并不能提高MySQL的性能,正确的做法是,根据 where 条件的情况,在多个列上建立组合索引。

使用多列索引,查询条件必须满足最左前缀原则,也就是说,where 条件的顺序与组合索引字段的顺序要保持一致。

比如我们在字段1和字段2上建立组合索引,而查询条件只有字段2,此时并不会走索引进行查询。

  • 覆盖索引

索引确实是一种查找数据的高效方式,但是 MySQL 也可以直接使用索引获取列的数据,这样就不再需要读取数据行了。

如果一个索引包含所有需要查询的字段的值,我们就称之为 覆盖索引

比如我们要查询用户的角色,一个用户会有多种角色,通常我们在 用户ID和角色ID 建立一个索引,这样我们查询用户的角色ID列表的时候,直接可以通过索引返回,不需要再回表。

  • 利用索引进行排序

当索引的顺序和 ORDER BY 子句的顺序完全一致,并且所有列的排序方向都一样时,MySQL 能够使用索引来对结果做排序。

比如,我们经常需要根据创建时间进行排序,那么在创建时间字段上建立一个索引,在进行排序查询的时候就会高效很多。

当 ORDER BY 子句不满足索引的最左前缀的要求时,就无法利用索引进行排序。

当然,特殊情况,也就是说,假如 ORDER BY 子句是从索引的第二个字段开始,但是索引的第一个字段被至指定为常数,也可以用于查询排序。

  • 创建区分度高的索引

比如,用户性别,我们知道性别取值一般是 男和女 ,也就两个值,重复率很高,如果在性别字段上创建索引,那么索引的效率就很低。

再比如,用户身份证号,每个人的身份证号都是不同的,在身份证号字段上建立索引,区分度就非常,根据身份证号索引的效率就很高。

总结

在选择索引和编写利用这些索引的查询时,需要根据具体业务情况来定,没有万能的方法。不过一般我们需要记住下面几个原则:

  • 单行访问是很慢的。如果服务器从存储中读取一个数据块只是为了获取某一行数据,那么就浪费了很多工作。最好读取的数据块中包含尽可能多的数据行。

  • 按顺序访问范围数据是很快的。原因是:第一,顺序I/O不需要多次磁盘寻道,比随机I/O要快得多;第二,如果服务器能按顺序读取数据,那么就不需要额外进行排序操作了。

  • 索引覆盖查询时很快的。如果一个索引包含了查询需要的所有列,那么存储引擎就不需要再回表查找数据行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章