聚集索引和非聚集索引
聚集索引
定义:数据行的物理顺序与列值(一般指主键)的逻辑顺序相同,一个表中只能拥有一个聚集索引
定义的解释
第一列的地址表示改行数据在磁盘中的物理地址,后面的是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)
注意:最好在创建表的时候添加聚集索引,由于聚集索引的物理顺序比较特殊,因此如果再在上面创建索引的时候会根据索引列的排列移动全部数据行上面的顺序,会非常地耗费时间以及性能。
非聚集索引
定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
其实按照定义,处理聚集索引以外的索引都是非聚集索引,只是又会细分一下(普通索引,唯一索引,全文索引),聚集索引类似字典中的偏旁,他结构顺序与实际存放顺序不一定一致。
非聚集索引的二次查询问题
非聚集索引叶节点任然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。
其中有聚集索引(id),非聚集索引index(username)
例:
使用以下语句进行查询,不需要进行二次查询,直接就可以从非聚集索引的节点里面获取到查询列的数据。
select id, username from t1 where username = '小明' select username from t1 where username = '小明'
但是使用以下的语句进行查询,就需要二次的查询去获取原数据行中的score
select username, score from t1 where username = '小明'
在SQL Server里面查询效率如下所示,Index Seek就是索引所花费的时间,Key Lookup就是二次查询所花费的时间。可以看的出二次查询所花费的查询开销占比很大,达到50%。
这篇博客有一个简单示例:https://blog.csdn.net/jiadajing267/article/details/54581262
关于何时使用聚集索引,和非聚集索引
需要注意的问题
一:聚集索引的约束是唯一性,是否要求字段也是唯一的呢?不要求唯一!
分析:一个表有一个主键,如果这个表之前没有聚集索引,同时建立主键的时候没有强制指定使用非聚集索引,sql会默认在此字段上 创建一个聚集索引, 而主键都是唯一的,所以就会认为创建聚集索引的字段也需要唯一。
结论:聚集索引可以创建在任何一列你想创建的字段上,实际不能随便指定,性能上会有影响。
二:为什么聚集索引可以创建在任何一列你想创建的字段上,如果此表没有书剑约束,可能存在重复行数据
分析:如果未使用UNIQUE属性创建聚集索引,数据库引擎将向表自动添加一个四字节 uniqueifier 列。必要时,数据库引擎将向行自 动添加一个四字节 uniqueifier 值,使每个键唯一。此列和列值供内部使用,用户不能查看或访问。
三:是不是聚集索引就一定是比非聚集索引性能优呢?
如果想查询学分在60-90之间的学生的分数以及姓名,在学分上创建聚集索引是否是最优的呢?
答:否,既然只输出两列,我们可以子啊学分以及学生姓名上创建联合非聚集索引,此时的索引就形成了覆盖索引,即索引所存储 的内容就是最终输出的数据,这种索引在此比以学分为聚集索引做查询性能更好。
四:在数据库中通过什么描述聚集索引和非聚集索引的?
索引是通过二叉树的形式进行描述的,我们可以这样区分聚集与非聚集索引的区别:聚集索引的叶节点就是最终的数据杰斯安,二非聚集索引的叶节点任然是索引节点,但它有一个指向最终数据的指针。
五:在主键是创建聚集索引的表在数据插入上为什么比主键上创建非聚集索引表速度要慢?
在有主键的表中插入数据,由于主键约束的唯一性,所以要保证插入的数据没有重复。
比较主键为聚集索引和非聚集索引的查找情况
聚集索引:索引节点就是数据页,索引想检查主键的唯一性,需要遍历所有数据节点
非聚集索引:上已经包含了主键值,所以查找主键唯一性,只需要遍历所有的索引页就行(索引的存储空间比实际数据更少)
所以插入数据时,主键上创建非聚集索引比主键上创建聚集索引快