Mysql聚簇索引和非聚簇索引
聚簇索引 并不是单独的索引类型,而是一种数据存储方式。术语“聚簇” 表示数据行和相邻的键值紧凑的存储在一起。《高性能Mysql》
参考链接
区别
存储方式上
- 聚簇索引
数据行和相邻的键值紧凑的存储在一起,就叫 聚簇,通俗讲,在Innodb中叶子节点存储的是主键值和数据行,则这就是聚簇索引,即 innodb的主键索引也叫聚簇索引。
- 非聚簇索引
数据行 和 相邻的键值的是分别存储的 ,myisam的存储引擎就是 索引文件和数据文件是分别存储的,叶子节点存储是 索引值和 指向记录行的地址
数据分布和查找
- 聚簇表(innodb)
主键索引:叶子节点存储的是 主键值和数据行,则找到主键值,则直接返回
二级索引(辅助索引):叶子节存储的是 索引值和对应的主键值。找到了索引值,回表 在根据主键值去 聚簇索引中找到对应的数据行。
- 非聚簇表(myisam)
主键索引 和 二级索引,叶子节点存储的是【索引类型值+对应的数据记录的指针】,找到该叶子节点后,再根据 数据记录的指针去对应的【数据文件中查询】
聚集数据的优缺点
优点
- 可以将相关的数据保存在一起。(因为聚簇索引的特点)
- 数据访问更快(无需回表查询,叶子节点保存的有 数据行记录)
- 使用覆盖 索引扫描的查询,可以直接使用页节点中的 主键值,去扫描。(快)
缺点
- 插入速度严重依赖插入顺序(如果随机插入,则每次都要计算合适的插入位置或者插入页分裂)
- 二级索引的查找数据,需要两次,而不是一次。
- 插入新行 或者 主键被更新,页可能会发生
页分裂,页分裂可能会导致占用更多的存储空间
Q&A
为什么 二级索引(innodb) 叶子节点存储的是主键值而不是地址
二级索引的组织关系时 <key,primaryKey>,
innodb 二级索引的叶子节点存储的不是 行指针,而是主键值,
目的: 减少了当出现行移动 或者 数据页分裂是 二级索引的维护工作。
缺点: 使用主键值当做指针会让二级索引占用更多的空间
优点: innodb在移动时,无需更新二级索引中的 这个 指针
为什么说,二级索引也是 非聚簇索引呢?
因为二级索引它的叶子节点 存储的是 索引值和主键值,并没有存储数据行,并不符合 聚簇索引的定义 数据行和相邻的键值紧凑的存储在一起
什么是页分裂
插入的主键的顺序不是顺序的插入,则可能发生页分裂
页分裂的目的:后一个数据页中的 所有行主键值比前一个数据页中主键值大
主键索引(UUID)缺点
-
要写入的目标页可能已经 刷到磁盘上并从缓冲中移除,或者还没有加载到缓存中,所以在插入之前,需要从磁盘中读取目标页到内存中,这将导致大量的随机IO。
-
因为是乱序写入的,innodb不等不频繁做 页分裂操作,为其找到合适的插入位置。页分裂会导致大量的数据移动。
-
由于频繁的页分裂,页会的变稀疏并不规则地填充,所以最红数据会有碎片(页还有剩余的空闲空间)
主键索引(自增顺序的)
因为主键的值是顺序的,所以每次新插入的记录 总是在 上一次记录的后面,当达到页的的最大填充因子(默认16kb),下一条记录会新的页中。并不会像 uuid这样的数据分布的不均匀