理解聚簇索引

聚簇索引(Cluster Index)也叫索引组织表(Index-organized Table),MySQL用户经常称呼为前者。聚簇索引并不是数据库索引的某个种类,其描述的是数据的一种存储方式。我们知道,在InnoDB中,数据是以B+Tree的形式存储的,其特点就是数据都存储在叶子节点上,非叶子节点上只存索引信息,即key值和指向子节点的指针。这种索引和数据的存储方式就叫做聚簇索引,“聚簇”的意思就是通常来说,数据行和相邻的健挨着。

InnoDB通过主键来聚集数据,也就是说聚簇索引的B+Tree上的叶子结点所存储的key总是主键,如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,InnoDB会隐式地定义一个主键来聚集(存储)数据,这个隐式的主键被称为rowID。

在InnoDB中,存储聚簇索引的B+Tree的叶子节点是一个数据页,默认大小为16K,这些数据页上的数据其实是一个有序链表,会按照主键递增的顺序来进行存储。在上图中,如果要访问ID为10的记录,InnoDB根据索引找到了key为11的索引,访问其左子节点,然后进行遍历(由于在一个数据页中的数据的存放位置是连续的,所以不会有多次寻址的额外开销),比较key值直到找到ID为10的记录。

对于非聚簇索引,InnoDB通常在叶子节点上存储的是数据行的主键值,命中非聚簇索引时,InnoDB会拿到此主键值再去聚簇索引中查询所需要的记录,这个过程称为回表。正是由于如此,所以通常来说聚簇索引的查询效率要比非聚簇索引高。

聚簇索引可能的缺点:

  • 由于聚簇索引在数据页内的顺序存储的特点,在插入操作中,插入速度很依赖插入的主键的顺序,倘若是非顺序插入,可能会导致为了保持顺序插入,在页内的其他位置的数据位置不得不移动。所以按照主键递增的顺序插入是最快的
  • 主键被更新时,数据行的存储位置不得不发生改变
  • 在插入新行时,可能造成数据页的空间不足(达到最大填充因子,默认为页大小的15/16),而不得不进行“页分裂”操作,增加额外开销
  • 当行比较稀疏,或者因为页分裂导致数据存储不连续时,全表扫描会变慢
  • 二级索引(非聚簇索引)的大小会依赖主键的大小,如果主键过大,会造成二级索引占用额外空间
  • 二级索引的查找需要两次搜索(一次查索引,一次回表操作)。当然二级索引这样设计也有其优势,就是当数据行的存储位置变化时,不用更新二级索引(因为主键值没有变)

聚簇索引叶子结点的结构

聚簇索引每一个叶子节点都包含主键值、事务ID、用于事务和MVCC的回滚指针、以及所有的剩余列。

为什么通常使用自增主键

  • InnoDB操作某一行时,会先讲此行所在的数据页加载到内存当中。如果使用连续主键,则很可能此数据页已经加载到内存中了。如果主键不连续,则这种情况命中的概率就小很多。InnoDB不得不在插入之前首先访问磁盘读取目标页到内存中,这将产生大量的随机IO
  • 乱序的主键插入可能会导致大量的页分裂操作,耗费额外资源
  • 频繁的页分裂会导致页中的数据分布不规则,且有可能变得稀疏,产生很多数据碎片

自增主键可能造成的问题

对于高并发的工作负载,InnoDB在插入操作时可能产生很多所争用的问题,这个时候主键的上界成为热点,因为所有的热点都发生在这里,所以并发插入可能会导致间隙锁竞争。

MyISAM的索引机制

MyISAM中的数据是按照插入的顺序存储的,而不是像InnoDB那样按照主键进行顺序存储的。其索引结构也比较简单,主键索引和二级索引并无差别,叶子节点存储的都是数据对应的行号或者地址(根据数据行是否为定长来采取不同的策略)。

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值