索引

索引的常见类型

哈希表

哈希表是一种以键 - 值(key-value)存储数据的结构。

这种结构适用于只有等值查询的场景。

有序数组

有序数组在等值查询和范围查询场景中的性能都非常优秀。但是由于插入操作需要移动数组,所以有序数组索引只适用于静态存储引擎。

搜索树

搜索树的查询复杂度是O(logN)、更新的时间复杂度也是O(logN)。

MyISAM和InnoDB存储引擎的表默认创建的是树索引

哈希表与搜索树

哈希索引有一些重要特征需要在使用的时候特别注意

  • 只用于使用=或<=>操作符的等式比较

  • 优化器不能使用哈希索引来加速ORDER BY操作

  • MySQL不能确定在两个值之间大约有多少行。如果将一个MyISAM表改为哈希索引的MEMORY表,会影响一些查询的执行效率。

  • 只能使用整个关键字来搜索一行

对于树索引,当使用>、<、>=、<=、BETWEEN、!=或者<>,或者LIKE 'pattern'(其中'pattern'不以通配符开始)操作符时,都可以使用相关列上的索引。

了解了BTREE索引和HASH索引不同后,当使用MEMORY表时,如果是默认创建的HASH索引,就要注意SQL语句的编写,确保可以使用上索引,如果一定要使用范围查询,那么在创建索引时,就应该选择创建成BTREE索引。

索引的设计原则

  • 最适合索引的列是出现在WHERE子句中的列,或连接子句中指定的列

  • 索引的列的基数越大,值越分散,索引的效果越好

  • 如果对字符串进行索引,应该指定一个前缀长度。

    • 较小的索引涉及的磁盘IO较少,较短的值比较起来更快。更为重要的是,对于较短的键值,索引高速缓存中的块能够容纳更多的键值,因此,MySQL也可以在内存中容纳更多的值。这样就增加了找到行而不用读取索引中较多块的可能性。

  • 不要过度索引,每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。

  • 对于InnoDB存储引擎的表,尽量自己指定主键。InnoDB表的普通索引会保存主键的键值,所以主键要尽可能选择较短的数据类型,可以有效地减少索引的磁盘占用,提高索引的缓存效果。

索引的使用

主键索引和普通索引的不同

主键索引的叶子解点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引。

非主键索引(普通索引)的叶子解点内容是主键的值。因此,主键长度越小,普通索引的叶子解点就越小,普通索引占用的空间也就越小。在InnoDB里,非主键索引也被称为二级索引。

普通索引查询方式,需要先查询出主键,再到主键索引树查询。这个过程称为回表。也就是说,基于非主键索引的查询需要多扫描一棵索引树。

覆盖索引

如果我们所需要查询的值已经在索引树上,就不需要回表。由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

最左前缀原则

B+树这种索引结构,可以利用索引的“最左前缀”来定位记录。即使用联合索引时,可以只使用左侧的索引字段。

存在索引但是不能使用索引的经典场景

  1. 以%开头的LIKE查询不能够利用B-Tree索引

  2. 数据类型出现隐式转换的时候也不会使用索引,特别是当列类型是字符串。

  3. 复合索引的情况下,假如查询条件不包含索引最左边部分,即不满足最左原则Leftmost,是不会使用复合索引的

  4. 如果MySQL估计使用索引比全表扫描更慢,则不使用索引

  5. 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到

Last updated