繁体   English   中英

为什么NonClustered索引扫描比聚簇索引扫描更快?

[英]Why NonClustered index scan faster than Clustered Index scan?

据我所知,堆表是没有聚簇索引的表,没有物理顺序。 我有一个堆栈表“扫描”有120k行,我使用这个选择:

SELECT id FROM scan

如果我为列“id”创建一个非聚集索引,我会得到223个物理读取 如果我删除非聚集索引并更改表以使“id”成为我的主键(以及我的聚簇索引),我将获得515个物理读取

如果聚集索引表是这样的图片:

在此输入图像描述

为什么Clustered Index Scans像表扫描一样工作? (或者在检索所有行的情况下更糟)。 为什么它不使用具有较少块的“聚簇索引表”并且已经具有我需要的ID?

SQL Server索引是b树。 非聚集索引仅包含索引列,b树的叶节点是指向适当数据页的指针。 聚簇索引是不同的:它的叶节点是数据页本身,聚簇索引的b树成为表本身的后备存储; 堆不再存在于表中。

您的非聚集索引包含一个可能是整数列。 这是一个小而紧凑的索引。 select id from scan查询select id from scan具有覆盖索引 :只需检查索引就可以满足查询,这就是正在发生的事情。 但是,如果您的查询包含不在索引中的列,假设优化程序选择使用非聚集索引,则需要额外的查找来从聚簇索引或堆中获取所需的数据页。

要了解发生了什么,您需要检查优化器选择的执行计划:

聚簇索引通常与堆中的相同数据一样大(假设页面完整性相同)。 由于额外的B树级别,它应该使用比堆更多的读取。

CI不能小于堆。 我不明白为什么你会这么想。 分区的大部分大小(无论是堆还是树)都在数据中。

请注意,较少的物理读取不一定转化为查询更快。 随机IO可能比顺序IO慢100倍。

何时使用聚集索引 -

查询注意事项:
1)使用BETWEEN,>,> =,<和<= 2等运算符返回一系列值。返回大的结果集
3)使用JOIN子句; 通常这些是外键列
4)使用ORDER BY或GROUP BY子句。 ORDER BY或GROUP BY子句中指定的列的索引可能不需要数据库引擎对数据进行排序,因为行已经排序。 这提高了查询性能。

列注意事项:考虑具有以下一个或多个属性的列:1)是唯一的或包含许多不同的值2)定义为IDENTITY,因为该列在表中保证是唯一的3)经常用于对从中检索的数据进行排序一张桌子

对于以下属性,聚簇索引不是一个好的选择:1)经常更改的列2)宽键

何时使用非聚集索引 -

查询注意事项:
1)使用JOIN或GROUP BY子句。 在连接和分组操作中涉及的列上创建多个非聚簇索引,并在任何外键列上创建聚簇索引。
2)不返回大型结果集的查询
3)包含经常涉及查询的搜索条件的列,例如WHERE子句,返回完全匹配

栏目注意事项
考虑具有以下一个或多个属性的列:
1)覆盖查询。 有关更多信息,请参阅包含列的索引
2)如果聚集索引用于其他列,则有许多不同的值,例如姓氏和名字的组合
3)经常用于对从表中检索的数据进行排序

数据库考虑因素:
1)具有较低更新要求的数据库或表,但是大量数据可以从许多非聚簇索引中受益,以提高查询性能。
2)包含大量更新表的联机事务处理应用程序和数据库应避免过度索引。 此外,索引应该是窄的,即尽可能少的列。

试试跑步

DBCC DROPCLEANBUFFERS

在查询之前......

如果你真的想比较它们。 优化查询时,物理读取与逻辑读取的含义不同

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM