Mysql聚簇索引和非聚簇索引

498 阅读4分钟

Mysql聚簇索引和非聚簇索引

聚簇索引 并不是单独的索引类型,而是一种数据存储方式。术语“聚簇” 表示数据行和相邻的键值紧凑的存储在一起。《高性能Mysql》

参考链接

聚簇索引和非聚簇索引理解

区别

存储方式上

  • 聚簇索引

数据行和相邻的键值紧凑的存储在一起,就叫 聚簇,通俗讲,在Innodb中叶子节点存储的是主键值和数据行,则这就是聚簇索引,即 innodb的主键索引也叫聚簇索引。

  • 非聚簇索引

数据行 和 相邻的键值的是分别存储的 ,myisam的存储引擎就是 索引文件和数据文件是分别存储的,叶子节点存储是 索引值和 指向记录行的地址

数据分布和查找

  • 聚簇表(innodb)

主键索引:叶子节点存储的是 主键值和数据行,则找到主键值,则直接返回

二级索引(辅助索引):叶子节存储的是 索引值和对应的主键值。找到了索引值,回表 在根据主键值去 聚簇索引中找到对应的数据行。

  • 非聚簇表(myisam)

主键索引 和 二级索引,叶子节点存储的是【索引类型值+对应的数据记录的指针】,找到该叶子节点后,再根据 数据记录的指针去对应的【数据文件中查询】

WechatIMG698.png

聚集数据的优缺点

优点

  • 可以将相关的数据保存在一起。(因为聚簇索引的特点)
  • 数据访问更快(无需回表查询,叶子节点保存的有 数据行记录)
  • 使用覆盖 索引扫描的查询,可以直接使用页节点中的 主键值,去扫描。(快)

缺点

  • 插入速度严重依赖插入顺序(如果随机插入,则每次都要计算合适的插入位置或者插入页分裂)
  • 二级索引的查找数据,需要两次,而不是一次。
  • 插入新行 或者 主键被更新,页可能会发生 页分裂,页分裂可能会导致占用更多的存储空间

Q&A

为什么 二级索引(innodb) 叶子节点存储的是主键值而不是地址

二级索引的组织关系时 <key,primaryKey>,

innodb 二级索引的叶子节点存储的不是 行指针,而是主键值,

目的: 减少了当出现行移动 或者 数据页分裂是 二级索引的维护工作。

缺点: 使用主键值当做指针会让二级索引占用更多的空间

优点: innodb在移动时,无需更新二级索引中的 这个 指针

为什么说,二级索引也是 非聚簇索引呢?

因为二级索引它的叶子节点 存储的是 索引值和主键值,并没有存储数据行,并不符合 聚簇索引的定义 数据行和相邻的键值紧凑的存储在一起

什么是页分裂

插入的主键的顺序不是顺序的插入,则可能发生页分裂

页分裂的目的:后一个数据页中的 所有行主键值比前一个数据页中主键值大

主键索引(UUID)缺点

  • 要写入的目标页可能已经 刷到磁盘上并从缓冲中移除,或者还没有加载到缓存中,所以在插入之前,需要从磁盘中读取目标页到内存中,这将导致大量的随机IO。

  • 因为是乱序写入的,innodb不等不频繁做 页分裂操作,为其找到合适的插入位置。页分裂会导致大量的数据移动。

  • 由于频繁的页分裂,页会的变稀疏并不规则地填充,所以最红数据会有碎片(页还有剩余的空闲空间)

主键索引(自增顺序的)

因为主键的值是顺序的,所以每次新插入的记录 总是在 上一次记录的后面,当达到页的的最大填充因子(默认16kb),下一条记录会新的页中。并不会像 uuid这样的数据分布的不均匀