1. 首页 > 快讯

聚集索引和非聚集索引总结

SQL Sever索引类型包括:唯一索引、主键索引、聚集索引、非聚集索引。

MySQL索引类型包括:唯一索引、主键(聚集)索引、非聚集索引、全文索引。

二. 聚集索引

聚集索引,也叫聚簇索引。

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

光从定义上看是不是有点抽象?比如表就像我们之前用的新华字典,聚集索引就像拼音目录,每个单词存储的页码就是我们数据的物理地址。我们如果要查询“哇”字,我们只需要在新华字典拼音目录中查询“哇”字对应的页码,就可以查询到对应的“哇”字的位置,拼音目录对应的A-Z词序,与新华字典中实际存储的字符A-Z顺序相同。如果我们有一个新的汉字,拼音开头的第一个字符是B,那么插入的时候,必须按照拼音目录的顺序插入到字符A之后。现在用一个简单的图来大致说明一下数据库中的样子:

地址idusernamescore0x011 Xiaoming900x022Xiaohong800x033Xiaohua92.0xff256Xiaoying70 注:第一列中的地址表示该行数据在磁盘上的物理地址,后面三列是我们SQL表中的列,其中id为主键,创建聚集索引。

结合上表就可以理解这句话:数据行的物理顺序与列值的顺序相同。如果我们查询后面的ID的数据,那么这行数据的地址也会和磁盘上的物理地址进行比较。退后一步。并且由于物理排列与聚集索引的顺序相同,因此只能创建一个聚集索引。

聚集索引实际存储示意图

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

创建聚集索引

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

1、创建表时指定主键(注:SQL Sever默认主键是聚集索引,也可以指定为非聚集索引,而MySQL中主键是聚集索引)

创建表t1(

id int 主键,

名称nvarchar(255)

2、建表后添加聚集索引

聚集索引和非聚集索引总结

SQL服务器

在表名(列名)上创建聚集索引clustered_index

MySQL

altertable table_name 添加主键(colum_name)

值得注意的是,创建表时最好添加聚集索引。由于聚集索引物理顺序的特殊性,如果在上面创建索引,所有的数据行都会按照索引列的顺序移动。这会消耗大量的时间和性能。

三. 非聚集索引

非聚集索引。

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

其实从定义上来说,聚集索引以外的索引都是非聚集索引,只不过人们想把非聚集索引细分为普通索引、唯一索引、全文索引。如果非要把非聚集索引比作现实生活中的一些东西,那么非聚集索引就像是新华字典的部首词典,它的结构顺序并不一定与实际的存储顺序一致。

非聚集索引实际存储示意图

聚合索引的二次查询问题

非聚集索引叶子节点仍然是索引节点,但有一个指向相应数据块的指针。如果使用非聚集索引查询,并且查询列包含索引未覆盖的其他列,那么会执行第二次。查询,查询节点上对应数据行的数据。

假如有下表t1:

idusernamescore1 小明902 小红803 小华92.256 小英70 聚集索引和聚集索引(id)、非聚集索引(username)。

使用下面的语句进行查询。无需执行第二次查询。可以直接从非聚集索引的节点获取查询列的数据。

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

从t1 中选择用户名,其中用户名='小明'

但使用如下语句进行查询,需要进行第二次查询才能获取原始数据行的分数:

聚集索引和非聚集索引总结

选择用户名,得分来自t1 其中username='Xiao Ming'

SQL Server中的查询效率如下。 Index Seek 是建立索引所花费的时间,Key Lookup 是二次查询所花费的时间。可以看到,花费在二次查询上的查询开销占比很大,达到了50%。

在SQL Server中,查询会自动优化并选择合适的索引。因此,如果数据量不大,SQL Server很可能不会使用非聚集索引进行查询,而是会使用聚集索引进行查询,即使有必要。扫描整个聚集索引比使用非聚集索引更有效。

我尝试在包含300,000 行的表上创建非聚集索引。查询非聚集索引覆盖的列以外的列,都会变成聚集索引的全索引扫描查询,避免二次查询。在另一个有200万行的表中,该表将使用非聚集索引查找对应的列,然后执行kek查找。关于SQL Server,有索引查找、索引扫描、表扫描、键查找等几个概念。您可以查看此博客以获取更详细的描述。

但在MySQL中,即使表的数据量很小并且查询的是非键列,也不会使用聚集索引来进行全索引扫描。但如果强制使用聚集索引进行查询,性能会比非聚集索引查询差。这是SQL 中的两个差异。

另外需要注意的是,非聚集索引的叶子节点不仅会存储索引覆盖的列的数据,还会存储聚集索引覆盖的列的数据。

如何解决非聚集索引的二次查询问题

综合索引(覆盖索引)

通过创建两列以上的索引,可以查询复合索引中各列的数据,无需二次查询回表,如index(col1, col2),执行以下语句

从t1 中选择col1、col2,其中col1='213';

需要注意的是,复合索引的使用需要满足最左边索引的原则。也就是说,如果查询时where条件中没有最左边的一列或多列,索引将不起作用。

SQL Server中还有include的使用,可以包含非聚集索引中包含的列,而不必构建复合索引。

四. 总结与使用心得

使用聚集索引的查询效率高于非聚集索引。但如果需要频繁改变聚集索引的值,则由于需要移动对应数据的物理位置,写入性能不高。

如果查询时能够使用非聚集索引,就可以避免二次查询,因此性能会得到很大的提高。

并不是所有的表都适合创建索引。只有数据量大的表才适合创建索引,并且索引建立在选择性高的列上,性能会更好。

用户评论

一笑傾城゛

索引真就是数据库优化的神技能!

    有19位网友表示赞同!

笑傲苍穹

学习数据库?这两类索引可别忘了啊!

    有12位网友表示赞同!

良人凉人

聚集索引排序方便,但插入或更新慢哦~

    有14位网友表示赞同!

南宫沐风

非聚集索引查询快,但遍历全表查询速度较慢。

    有16位网友表示赞同!

哽咽

总结得太棒了!我终于理解这两种索引的区别了

    有14位网友表示赞同!

见朕骑妓的时刻

数据量大吗?选个合适的索引很重要!

    有16位网友表示赞同!

那伤。眞美

聚合型和非聚合型的区别在于存储结构,真难记啊……

    有19位网友表示赞同!

泪湿青衫

明白了!聚集索引适合经常查询排名,非聚集索引适合根据条件快速筛选。

    有6位网友表示赞同!

封心锁爱

数据库学习太硬核了!这两种总结的应用场景挺有用的哦~

    有8位网友表示赞同!

清原

我要去强化我的索引操作技巧了!

    有19位网友表示赞同!

有你,很幸福

这个总结真清晰,比教科书还容易理解!

本文采摘于网络,不代表本站立场,转载联系作者并注明出处:https://www.iotsj.com//kuaixun/5664.html

联系我们

在线咨询:点击这里给我发消息

微信号:666666