欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
聚簇索引和非聚簇索引的区别?非聚集索引一定回表查询吗?
答:
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
当表里有聚簇索引时,它的数据行实际上存放在索引的叶子节点中。
聚簇
表示数据行和相邻和键值存储在一起
InnoDB 根据主键来聚簇数据,如果没有定义主键的话,InnoDB 会隐式定义一个主键来作为聚簇索引,
聚簇索引的优点:
- 数据访问更快。聚簇索引将数据和索引保存在同一个 B-tree 中,获取数据比非聚簇索引更快
- 使用覆盖索引扫描的查询可以直接使用叶节点的主键值
聚簇索引的缺点:
-
提升了 IO 密集型应用的性能。(如果数据全部放在内存中的话,不需要执行 IO 操作,聚集索引就没有什么优势了)
-
插入速度严重依赖于插入顺序。按照主键的顺序插入行是将数据加载到 InnoDB 表中最快的方式。
如果不是按照逐渐顺序加载数据,在加载完之后最好使用
optimize table
重新组织一下表,该操作会重建表。重建操作能更新索引统计数据并释放聚簇索引中的未使用的空间。可以使用
show table status like '[table_name]'
查看优化前后表占用的存储空间 -
更新聚集索引的代价很高。因为会强制 InnoDB 将每个被更新的行移动到新的位置
-
基于聚簇索引的表在插入新行是或者主键被更新到只需要移动行的时候,可能面临
页分裂
的问题,当行的主键值需要插入某个已经满了的页中时,存储引擎会将该页分裂成两个页面来存储,也就是页分裂操作,页分裂会导致表占用更多的磁盘空间
-
聚簇索引可能会导致全表扫描变慢,尤其是行比较稀疏或者由于页分裂导致数据存储不连续的时候
-
二级索引(也是非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点存储了指向行的主键列。
-
二级索引访问需要两次索引查找,而不是一次。
二级索引中,叶子节点保存的是指向行的主键值,那么如果通过二级索引进行查找,找到二级索引的叶子节点,会先获取对应数据的主键值,然后再根据这个值去聚簇索引中查找对应的行数据。(
两次索引查找
)
二级索引是什么?为什么已经有了聚集索引还需要使用二级索引?
答:
二级索引
是非主键索引,也是非聚集索引
(索引和数据分开存放),也就是在非主键的字段上创建的索引就是二级索引。
比如我们给一张表里的 name 字段加了一个索引,在插入数据的时候,就会重新创建一棵 B+ 树,在这棵 B+ 树中,就来存放 name 的二级索引。
即在二级索引中,索引是 name 值,数据(data)存放的是主键的值,第一次索引查找获取了主键值,之后根据主键值再去聚集索引中进行第二次查找,才可以找到对应的数据。
常见的二级索引:
- 唯一索引
- 普通索引
- 前缀索引:只适用于字符串类型的字段,取字符串的前几位字符作为前缀索引。
为什么已经有了聚簇索引还需要使用二级索引?
聚簇索引的叶子节点存储了完整的数据,而二级索引只存储了主键值,因此二级索引更节省空间。
如果需要为表建立多个索引的话,都是用聚簇索引的话,将占用大量的存储空间。
回表什么时候会发生?
当使用 SQL 查询时,如果走了索引,但是要查询的列并不全在索引上,因此还需要回表查询完整的数据
在非聚簇索引中,叶子节点保存的是主键的值,如果查询走的非聚簇索引,但是要查询的数据不只有主键的值,还有其他值,此时在非聚簇索引中拿到主键值,还需要再去聚簇索引回表查询,根据主键值查询到整行数据
-
聚簇索引和非聚簇索引如下,这里画图比较简略了
- 根据非聚簇索引查询的话,是通过普通的索引字段进行判断的(比如在 name 上建立索引,那就是通过 name 字段去非聚簇索引上进行查询)
- 根据聚簇索引查询的话,是通过主键进行判断的,直接从 SQL 语句中拿到主键值或者从非聚簇索引中拿到主键值,去聚簇索引中进行查询