InnDB 中的索引
聚簇索引
B+ 树索引有两个特点:
- 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
- 页内的记录按照主键的大小顺序排成一个单向链表
- 各个存放用户记录的页也是根据页中用户记录的主键大小排序成一个双向链表
- 存放目录项记录的页分为不同层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表
- B+ 树的叶子节点存储的是完整的用户记录,所谓的完整的用户记录,就是指整个记录中存储了所有的列的值(包括隐藏列)
我们把这种具有这两种特性的 B+ 树称为聚簇索引。所有完整的的用户记录都存放在这个聚簇索引的叶子节点处。这种聚簇索引并不需要我们在 MySQL 语句中显示的使用 INDEX 语句去创建,InnoDB 存储引擎会自动的为我们创建聚簇索引,在 InnoDB 存储引擎中,聚簇索引就是数据的存储方式(所有的用户记录都存储在了叶子节点上),也就是所谓的索引即数据,数据即索引。
**
二级索引
聚簇索引只能在搜索条件是主键时才能发挥作用,因为 B+ 树中的数据都是按照主键来进行排序的,当我们想以别的列来作为搜索条件时,我们可以多建几棵 B+ 树,不同的 B+ 树中的数据采用不同的排序规则。
二级索引与聚簇索引的几处不同:
- 所有排序都按对应的索引列指定的排序规则来进行排序的
- B+ 树的叶子节点存储的并不是完整的用户记录,而只是“索引列 + 主键列”这两个列的值。
联合索引
以多个列的大小为排序规则建立的 B+ 树称为联合索引,本质上也是一个二级索引
InnoDB 的 B+ 树索引注意事项
根页面
前面介绍 B+ 树索引的时候,为了大家理解上的方便,先把存放用户记录的叶子节点先画出来了,然后接着画存储目录项记录的内节点,实际上 B+ 树的形成过程是这样的:
- 每当某个表创建一个 B+ 树索引(聚簇索引不是人为创建的,默认都有)的时候,都会为这个索引创建一个根节点页面,最开始表中没有数据的时候,每个 B+ 树索引对应的根节点中,既没有用户记录,也没有目录项记录
- 随后向表中插入记录的时候,会先把用户记录存储到这个根节点中
当根节点中,可用空间用完的时候,然后又继续插入用户记录,此时根节点的所有用户记录都会复制到一个新分配的页中,比如 A 页,然后对这个新页进行页分裂操作,得到另一个 B 页,此时新插入的记录根据键值(也就是聚簇索引中的主键,二级索引中对应的索引列的值)的大小就会被分配到 A 页或者 B 页中去,而此时的根节点便升级为存储目录项记录的页。
这个过程需要注意的是:一个 B+ 树索引的根节点自诞生之日起。便不会在移动,这样只要我们对某个表建立一个索引,那么他的根节点的页号便会记录到某个地方,然后凡是 InnoDB 存储引擎需要用到这个索引的时候,都会从那个固定的地方取出根节点的页号,从而来访问这个索引。
内节点中目录项记录时唯一的
**
我们需要保证在 B+ 树的同一层内节点的目录项记录除了页号这个字段以外是唯一的。所以对于二级索引的内节点的目录项记录的内容实际是由三个部分构成的:
- 索引列的值
- 主键值
- 页号
MyISAM 中的索引方案介绍
InnoDB 中索引即数据,也就是聚簇索引的那棵 B+ 树的叶子节点中已经把所有完整的用户记录都包含了,而 MyISAM 的索引方案虽然也使用了树形结构,但是却将索引和数据分开存储
- 将表中的记录按照记录的插入顺序单独存储在一个文件中,称之为数据文件。这个文件并不划分若干个数据页,有多少记录就在这个文件中塞入多少记录就成了。我们可以通过行号而快速的访问到某一条记录。
- 使用 MyISAM 存储引擎的表会把索引信息另外存储到一个称为索引文件的另一个文件中,MyISAM 会单独为表的主键创建一个索引,只不过在索引的叶子节点中存储的并不是完整的用户记录,而是“主键值 + 行号”的组合,也就是先通过索引找到对应的行号,再通过行号查找对应的记录。这点和 InnoDB 是完全不同的,再 InnoDB 存储引擎中,我们只需要根据主键值对聚簇索引进行一次查找就能找到相应的记录,而再 MyISAM 中却需要进行一次回表操作,意味着 MyISAM 中建立的索引相当于全部都是二级索引。
- 如果有需要的话,我们也可以对其他的列分别建立索引或者联合索引,原理和 InnoDB 中的索引差不多,不过在叶子节点处存储的是:“相应的列 + 行号”,这些索引页全是二级索引。