聚簇索引和非聚簇索引

目录

索引

  索引在数据库中的作用类似于目录在书籍中的作用,用来提高查找信息的速度。使用索引查找数据,无需对整表进行扫描,可以快速找到所需数据。这里主要简单讲解下两种索引:聚簇索引(也称聚类索引、簇集索引)和非聚簇索引(也称非聚类索引、非簇集索引)。

聚簇索引

  聚簇索引并不是数据库索引的某种类型,其描述的是数据的一种存储方式。我们知道,在InnoDB中,数据是以B+树的形式来进行存储的,其特点就是数据都存储在叶子节点上,非叶子节点值存储索引信息,既Key和指向子节点的指针。这种索引和数据的存储方式叫做聚簇索引。通常来说,“聚簇”的意思是数据行和键紧挨着。我们一般设置主键索引就为聚簇索引。

  一个没加主键的表,其数据无序的放置在磁盘上,一行一行排列得很整齐。如果给表加上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是平衡树结构,换句话说,就是整个表就变成了一个索引,也就是所谓的聚簇索引。这就是为什么一个表只能有一个主键,一个表只能有一个聚簇索引的原因,因为主键的作用就是把表的数据结构格式转换成索引的格式来放置。

 
在这里插入图片描述

 
在该树状结构中,除叶子节点外,树中的所有节点的数据都是由主键字段中的数据构成,也就是我们通常指定作为主键的 ID 字段。在叶子节点部分才是我们存表中数据的地方。

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

而在InnoDB中,聚簇索引的B+树的叶子节点是一个数据页,默认大小为16K,这些叶子节点,也就是数据页的数据其实是一个有序链表,会按照主键递增的顺序来存储。如果我们要访问 ID 为10的记录,InnoDB根据索引找到了key为11的所有,访问其左节点,比较key值直到找到为止。
 
在这里插入图片描述
 

非聚簇索引

讲完聚簇索引,接下来我们来聊一下非聚簇索引,也就是我们平常经常提起和使用的常规索引。

非聚簇索引和聚簇索引,同样是采用平衡树来作为索引的数据结构。索引树结构中各个节点的值来自于表中的索引字段。我们假如给user表的name加上索引,那么索引就是由name字段中的值来构成,在数据改变时,DBMS需要一直维护索引结构的正确性。如果给表中的多个字段加上索引,那么就会出现多个独立的索引结构,非聚簇索引,每个索引互相之间不存在关联。

每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。

在这里插入图片描述

聚簇索引和非聚簇索引的区别

  • 聚集索引可以一次查到需要查找的数据,而通过非聚集索引第一次只能查到记录对应的主键值再去聚簇索引中查询所需要的记录,这个过程称为回表。正是由于如此,所以通常来说聚簇索引的查询效率要比非聚簇索引高。
  • 聚集索引一张表只能有一个,而非聚集索引一张表可以有多个
一、聚集索引

定义:数据行的物理顺序与列值(一般是主键的那一列)的 逻辑顺序相同,一个表中只能拥有一个聚集索引。

: 1、由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了。

        2、从下图可以看出聚集索引的好处了,索引的 叶子节点就是对应的数据节点,可以直接获取到对应的全部列的数据,而非聚集索引在索引没有覆盖到对应的列的时候需要进行二次查询,后面会详细讲。因此在查询方面聚集索引的速度往往会更占优势。

        3、如果不创建索引,系统会自动创建一个隐含列作为表的聚集索引。

        4、SQL Sever默认主键为聚集索引,也可以指定为非聚集索引,而MySQL里主键就是聚集索引

 

二、非聚集索引

定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。

: 1、其实按照定义,除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,分成普通索引,唯一索引,全文索引。如果非要把非聚集索引类比成现实生活中的东西,那么非聚集索引就像新华字典的偏旁字典,他结构顺序与实际存放顺序不一定一致。

        2、非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。

        3、使用以下语句进行查询,不需要进行二次查询,直接就可以从非聚集索引的节点里面就可以获取到查询列的数据。

select id, username from t1 where username = '小明' 
select username from t1 where username = '小明'

        4、但是使用以下语句进行查询,就需要二次的查询去获取原数据行的score:

select username, score from t1 where username = '小明'

        5、可以看的出二次查询所花费的查询开销占比很大,达到50%。

        6、聚集索引与非聚集索引区别原理图如下(如果有看不懂可以在评论区留言)

三、根本区别

1、区别:数据行的物理顺序与表的某个列值的逻辑顺序是否一致。

2、使用示例证明:

第一步:创建表和插入相关测试数据

create database IndexDemo 
go 
use IndexDemo 
go 
create table ABC 
( 
A int not null, 
B char(10), 
C varchar(10) 
) 
go 
insert into ABC select 1,'B','C' 
union select 5,'B','C' 
union select 7,'B','C' 
union select 9,'B','C' 
go select * from abc

第二步:插入一条数据

insert into abc values('6','B','C')

第三步:创建聚集索引(注意:排列变成有序

create clustered index CLU_ABC on abc(A) 

第四步:删除聚集索引(注意:排列变成无序

drop index abc.CLU_ABC

第五步:非聚集索引,添加新的记录,查看表顺序,如图四,并没有影响表的顺序

create nonclustered index NONCLU_ABC on abc(A)
insert into abc values('4','B','C') 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值