InnoDB 的索引模型基础

在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。
主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。
非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。
查询使用非主键索引,需要先在非主键索引的B+树查询对应的主键 id 再回主键索引的B+树查数据 这个操作称为回表 。也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。所以主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。一般设置 int 或 bigint

索引维护

B+树为了维护索引有序性,在插入新值的时候需要做必要的维护如果插入下一个自增,则只需要在对应的记录后面插入一个新记录。如果新插入的 ID 值是已有 Id 的中间值,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置。
而更糟的情况是,如果所在的数据页已经满了,根据B+树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。

覆盖索引

上面提到查询非主键索引需要回表。那么,有没有可能经过索引优化,避免回表过程呢。可以使用覆盖索引,比如:你需要查询 name 为‘陈某’的id,那么就不需要回表了。也就是说,在这个查询里面,索引 name 已经“覆盖了”我们的查询需求,我们称为覆盖索引。由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

前缀索引

B+树这种索引结构,可以利用索引的“最左前缀”,来定位记录。比如:你要查的是所有名字第一个字是“陈”的人,你的SQL语句的条件是”where name like ‘陈%’”。这时,你也能够用上这个索引。可以看到,不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左字符串索引。
下面我们来讲讲在建立联合索引的时候,如何安排索引内的字段顺序。 这里我们的评估标准是,索引的复用能力。因为可以支持最左前缀,所以当已经有了(a,b)这个联合索引后,一般就不需要单独在a上建立索引了。因此,第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。

索引下推

MySQL 5.6 引入的索引下推优化(index condition pushdown),, 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
联合索引(name, age)为例。比如:检索出表中名字第一个字是陈,而且年龄是10岁的所有男孩信息。在数据中姓“陈”有很多个,meysql 不会把所有的姓陈的主键拿到回表读取数据。它会先判断下 age 是否满足条件,对于不等于10的记录,直接判断并跳过,减少不必要的回表。
information_schema.innodb_trx–当前运行的所有事务