文章标题
- 聚簇索引
- 非聚簇索引
- 联合索引
- B+树索引的注意点
索引按照物理实现方式,索引可以分为2种:
聚簇索引和
非聚簇索引
非聚簇索引又被称为二级索引
或者辅助索引
也可以称为聚集索引、非聚集索引
聚簇索引
聚簇索引指的是一种数据的存储方式,即将所有的记录存储在叶子节点,就是索引即数据、数据即索引
而聚簇是指数据行和相邻的键值存储在一起,就是索引和数据是一个整体的。
特点:
- 根据主键的大小进行记录和数据页的排序( 1.一个数据页内的多个记录是根据主键的大小排成一个单链表2.各个数据页也是根据主键的大小排成一个双链表3.每一层的数据页中也是根据主键的大小进行排序)
- 叶子节点中存储的是完整的数据记录(完整记录指一条记录中包括了所有字段的值,包括隐藏字段/隐藏列的值)
具有以上两个特点的B+树就是聚簇索引
,聚簇索引的叶子节点中包含了所有的记录。
当我们在MySQL客户端中用insert插入一条记录时,Innodb
存储引擎会自动的帮我们创建聚簇索引
简单地说,聚簇索引就是根据主键搭建起来的一个B+树,在插入数据的时候自动创建
优点:
- 数据访问更快,因为聚簇索引将数据和索引保存在同一个树中,因此获取速度比非聚簇索引要快
- 对于主键的排序查找和范围查找更快(本身就是有序的)
- 数据成块出现,节省大量IO操作
缺点:
- 插入速度严重依赖插入顺序.
按照主键顺序插入是最快的,如果不按主键插入,就会发生页分裂,重新调整顺序,比如上一条记录的主键是45,下一条主键是78,如果此时插入主键为40的记录,就需要先将前两个记录挪到后面,然后将这个记录添加到前面。
- 更新主键的代价高。主键更改,该记录就会移动,其他记录也会被迫移动,变动太大,主键通常定义不可更新
- 二级索引访问需要两次索引查找。第一次找到主键值,第二次根据主键值找到行数据.
限制:
- MySQL数据库中只有Innodb支持聚簇索引,MyISAM不支持
- 每个表只能有一个聚簇索引,一般为该表的主键,因为数据物理存储排序方式唯一。
- 没有定义主键时,Innodb会选择
非空的唯一索引
代替, 如果没有这样的索引,Innodb会隐式的定义一个主键作为聚集索引 - 选择主键时,尽量用有序的顺序id,用无序id像字符串等可能无法保证数据的顺序增长
非聚簇索引
非聚簇索引也被称为辅助索引、二级索引
非聚簇索引选择非主键的字段作为索引,在叶子节点中不存储真实数据,只存储数据位置(即这个数据在哪个主键下),然后根据位置到聚簇索引中进行查找数据,这个过程也叫回表。
为什么需要回表?
因为我们如果在每一课B+树中都储存一次数据的话非常浪费空间,我们让带有主键的聚簇来存数据,让其他的非聚簇只存主键,然后根据这个主键回表查询数据.这也是非聚簇被称为二级索引、辅助索引的原因。
innodb中的索引分布:
一个聚簇,多个非聚簇.
回表
两个索引的区别:
- 聚簇索引的叶子节点储存的是真实数据,而非聚簇的叶子节点储存的是数据位置
- 一个表只能有一个聚簇,但可以有多个聚簇索引
- 聚簇索引的查找效率高(不用回表),非聚簇的增删改效率高
联合索引
严格意义上,联合索引属于非聚簇索引。
联合索引就是用多个字段作为索引.
在叶子节点中储存这个几个字段的数值,先按照其中一个字段进行排序,相同时再按照另一个字段进行排序。
比如用C2、C3字段作联合索引,先按C2进行排序,C2相同时再按照C3进行排序,在叶子中,不仅有C2、C3,还有作为主键的C1,需要依靠C1去聚簇中找到这个数据(回表)
B+树索引的注意点
- 根节点位置不变
1.前面我们自下而上的模拟过B+树的创建过程,实际的过程是自上而下的
2.在没有向表中插入记录的时候,会有一个默认的空的根节点
3.然后向表中插入记录,这些记录会先保存到根节点
4.当根节点满了后,会将所有的记录复制到一个新的数据页,然后不断的添加数据,不断的页分裂
5.根节点原来的记录会全部清除,开始保存目录数据,当空间再次用完,会复制这些目录数据到一个新页,然后再次清除,保存目录的目录…然后再满、再清除、再分裂…不断迭代
- 非叶子节点中目录是唯一的
聚簇索引都含有主键,所以一定唯一,而非聚簇中的那些字段如何保证唯一性?
比如用C2作为字段,如果C2有两个相同的值该如何?其实在二级索引中,不只有叶子节点中带有主键,其实非叶子节点中也带有主键,目的就是保证唯一性,避免上面情况
- 一个数据页中最少要存2条记录