数据库的聚集索引和非聚集索引

聚集(clustered)索引,也叫聚簇索引

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

注:第一列的地址表示该行数据在磁盘中的物理地址,后面三列才是我们SQL里面用的表里的列,其中id是主键,建立了聚集索引。

结合上面的表格就可以理解这句话了吧:数据行的物理顺序与列值的顺序相同,如果我们查询id比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较靠后。而且由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了。
在这里插入图片描述

从上图可以看出聚集索引的好处了,索引的叶子节点就是对应的数据节点(MySQL的MyISAM除外,此存储引擎的聚集索引和非聚集索引只多了个唯一约束,其他没什么区别),可以直接获取到对应的全部列的数据,而非聚集索引在索引没有覆盖到对应的列的时候需要进行二次查询,后面会详细讲。因此在查询方面,聚集索引的速度往往会更占优势

创建聚集索引

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

1.创建表的时候指定主键(注意:SQL Sever默认主键为聚集索引,也可以指定为非聚集索引,而MySQL里主键就是聚集索引)

create table t1(
    id int primary key,
    name nvarchar(255)
 
)

2.创建表后添加聚集索引

MySQL

alter table table_name add primary key(colum_name)

值得注意的是,最好还是在创建表的时候添加聚集索引,由于聚集索引的物理顺序上的特殊性,因此如果再在上面创建索引的时候会根据索引列的排序移动全部数据行上面的顺序,会非常地耗费时间以及性能。


非聚集(unclustered)索引

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

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

非聚集索引的二次查询问题

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

有表t1:
在这里插入图片描述
其中有 聚集索引clustered index(id), 非聚集索引index(username)。

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

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

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

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

总结

聚集索引和非聚集索引的根本区别是表中记录的物理顺序和索引的排列顺序是否一致,本质是叶子节点的索引文件和数据文件是否分离的

建议使用聚集索引的场合为:

  • 某列包含了小数目的不同值。

  • 排序和范围查找。 非聚集索引的记录的物理顺序和索引的顺序不一致。

建议使用非聚集索引的场合为:

  • 此列包含了大数目的不同值;

  • 频繁更新的列

其他方面的区别:
1.聚集索引和非聚集索引都采用了 B+树的结构,但非聚集索引的叶子层并 不与实际的数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中 的指针的方式。聚集索引的叶节点就是数据节点,而非聚集索引的叶节点仍然 是索引节点。

2.非聚集索引添加记录时,不会引起数据顺序的重组。

基于主键索引和普通索引的查询有什么区别?

mysql> create table T( 
	id int primary key,
	k int not null,
	name varchar(16),
	index (k)) engine=InnoDB;

(ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6)

主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚集索引(clustered index)。

非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)

如果语句是 select * from T where ID=500,即 主键查询方式,则只需要搜索 ID 这棵 B+树

如果语句是 select * from T where k=5,即 普通索引查询方式,则需要先搜索 k 索引树,得到 ID的值为 500,再到 ID 索引树搜索一次。这个过程称为回表

B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。以上面为例,如果插入新的行 ID 值为 700,则只只需要在 R5 的记录后面插入一个新记录。如果新插入的 ID值为 400,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置。

参考文章:
https://blog.csdn.net/qq_29373285/article/details/85254407
https://blog.csdn.net/qq_43193797/article/details/88593304
http://blog.itpub.net/30126024/viewspace-2221485/

发布了107 篇原创文章 · 获赞 14 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/belongtocode/article/details/103378750