辨析覆盖索引/索引覆盖
既然多个列可以组合起来构建为联合索引,那么辅助索引自然也可以由多个列组 成。 覆盖索引也是我们经常见到的名词,InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询的记录,而不需要查询聚
集索引中的记录。使用覆盖索引的一个好处是辅助索引不包含整行记录的所有信 息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。所以记住,覆盖索 引可以视为索引优化的一种方式,而并不是索引类型的一种。 除了覆盖索引这个概念外,在索引优化的范围内,还有前缀索引、三星索引等一系 列概念,都会在我们后面的课程中学习到。
查询中的使用
索引在查询中的作用到底是什么?在我们的查询中发挥着什么样的作用呢? 请记住:
1、一个索引就是一个B+树,索引让我们的查询可以快速定位和扫描到我们需要的数据 记录上,加快查询的速度。 2、一个select查询语句在执行过程中一般最多能使用一个二级索引来加快查询,即使 在where条件中用了多个二级索引。
索引的代价
世界上从来没有只有好处没有坏处的东西,如果你有,请你一定要告诉我,让我也感受 一下。虽然索引是个好东西,在学习如何更好的使用索引之前先要了解一下使用它的代 价,它在空间和时间上都会拖后腿。
空间上的代价
这个是显而易见的,每建立一个索引都要为它建立一棵B+树,每一棵B+树的每一个节点 都是一个数据页,一个页默认会占用16KB的存储空间,一棵很大的B+树由许多数据页组 成会占据很多的存储空间
时间上的代价
每次对表中的数据进行增、删、改操作时,都需要去修改各个B+树索引。而且我们讲 过,B+树每层节点都是按照索引列的值从小到大的顺序排序而组成了双向链表。不论是
叶子节点中的记录,还是非叶子内节点中的记录都是按照索引列的值从小到大的顺序而 形成了一个单向链表。 而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间 进行一些记录移位,页面分裂、页面回收的操作来维护好节点和记录的排序。如果我们 建了许多索引,每个索引对应的B+树都要进行相关的维护操作,这必然会对性能造成影 响。 既然索引这么有用,我们是不是创建越多越好?既然索引有代价,我们还是别创建了 吧?当然不是!按照经验,一般来说,一张表6-7个索引以下都能够取得比较好的性能权 衡。 那么创建索引的时候有什么好的策略让我们充分利用索引呢?
高性能的索引创建策略
正确地创建和使用索引是实现高性能查询的基础。前面我们已经了解了索引相关的数据 结构,各种类型的索引及其对应的优缺点。现在我们一起来看看如何真正地发挥这些索 引的优势。
索引列的类型尽量小
我们在定义表结构的时候要显式的指定列的类型,以整数类型为例,有TTNYINT、 NEDUMNT、INT、BIGTNT这么几种,它们占用的存储空间依次递增,我们这里所说的类型 大小指的就是该类型表示的数据范围的大小。能表示的整数范围当然也是依次递增,如 果我们想要对某个整数列建立索引的话,在表示的整数范围允许的情况下,尽量让索引 列使用较小的类型,比如我们能使用INT就不要使用BIGINT,能使用NEDIUMINT就不要使 用INT,这是因为: ·数据类型越小,在查询时进行的比较操作越快(CPU层次) ·数据类型越小,索引占用的存储空间就越少,在一个数据页内就可以放下更多的记 录,从而减少磁盘/0带来的性能损耗,也就意味着可以把更多的数据页缓存在内存中, 从而加快读写效率。 这个建议对于表的主键来说更加适用,因为不仅是聚簇索引中会存储主键值,其他所有 的二级索引的节点处都会存储一份记录的主键值,如果主键适用更小的数据类型,也就 意味着节省更多的存储空间和更高效的I/0。
利用索引选择性和前缀索引 索引的选择性/离散性
创建索引应该选择选择性/离散性高的列。索引的选择性/离散性是指,不重复的索引值 (也称为基数,cardinality)和数据表的记录总数(N)的比值,范围从1/N到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多 的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。 很差的索引选择性就是列中的数据重复度很高,比如性别字段,不考虑政治正确的情况 下,只有两者可能,男或女。那么我们在查询时,即使使用这个索引,从概率的角度来 说,依然可能查出一半的数据出来。 比如下面这个表: