是什么?
聚簇索引:也叫主键索引,是将索引和数据放在一起,聚簇索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;找到索引也就找到了数据。
非聚簇索引:是指二级索引,也叫辅助索引。通过非聚簇索引可以查到记录对应的主键值,再使用主键的值通过聚簇索引找到要查找的数据。
Innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值。
区别是什么?
1.数据存储方式:
2.主键与索引关系:
- 聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。InnoDB 只聚集在同一个页面中的记录。包含相邻键值的页面可能相距甚远。如果你已经设置了主键为聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。
- 非聚簇索引可以在表的任何列上创建,不限于主键。
3.数据查找效率:
4.范围查询性能: (后面有详细介绍)
5.插入和删除操作影响:
聚簇索引的优势
- 查找数据更快:由于行数据和叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中,再次访问的时候,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。
- 聚簇索引适合用在排序的场合,非聚簇索引不适合:
聚簇索引中,数据是按照索引键的顺序物理存储的。这意味着,如果按照聚簇索引的键进行排序查询,数据库不需要额外的排序操作,因为数据本身已经是有序的。
例如,有一个订单表,按照订单号建立了聚簇索引。当需要按照订单号升序或降序获取订单信息时,数据库可以直接按照存储顺序读取数据,效率很高。
而非聚簇索引中,索引的叶子节点存储的是指向数据的指针,数据本身的存储顺序与索引键的顺序无关。当基于非聚簇索引进行排序查询时,数据库首先需要通过索引找到数据的指针,然后再根据指针获取数据,并在内存中进行排序操作。这增加了额外的开销,效率相对较低。
假设一个客户表,以客户 ID 建立了非聚簇索引,而数据按照注册时间存储。如果要按照客户 ID 排序获取客户信息,数据库需要先通过非聚簇索引找到数据指针,再获取数据并排序。
-
可以把相关数据保存在一起:
以电子邮箱为例,如果按照用户 ID 建立了聚簇索引,那么属于同一个用户的所有邮件数据在物理存储上会靠在一起。当您要获取某个用户的全部邮件时,只需要从磁盘读取相对较少的数据页就行。
但如果没有使用聚簇索引,每个邮件可能在磁盘上随机分布,那么获取每一封邮件都可能需要单独从磁盘读取一次,这会大大增加磁盘操作的次数,降低效率。
非聚簇索引的优势
如果辅助索引使用地址值作为指针,会存在一些问题。当数据库中的行发生移动,比如由于插入或删除操作导致 B+树节点分裂,或者数据页分裂时,原来存储的地址值就可能变得无效或者不准确。为了保持辅助索引的正确性,数据库就需要花费额外的资源和时间去更新这些地址指针,这就增加了辅助索引的维护工作,会影响数据库的性能。
然而,如果辅助索引使用主键作为“指针”,情况就有所不同(实际就是这个)。虽然这样做会使得辅助索引占用更多的空间,因为主键通常比地址值占用更多字节。但换来的好处是显著的。
在 InnoDB 存储引擎中,行的位置实际上是通过 16K 的 Page 来定位的。随着数据库中数据的不断修改,比如频繁的插入、删除操作,可能会导致前面提到的 B+树节点分裂以及 Page 的分裂。这就会使得行的实际存储位置发生变化。
但因为辅助索引使用的是主键值作为指针,只要主键值本身不变,无论主键所在的 B+树节点如何变化,辅助索引都无需更新这个“指针”。
再进一步说,当使用聚簇索引时,由于聚簇索引决定了数据的物理存储顺序,并且主键是聚簇索引的一部分。所以,即使聚簇索引中的主键 B+树节点发生了变化,只要主键值不变,辅助索引树就能够保持稳定,不受这些变化的影响。