聚集索引和非聚集索引之间的区别 [重复]

Posted

技术标签:

【中文标题】聚集索引和非聚集索引之间的区别 [重复]【英文标题】:Difference between clustered and nonclustered index [duplicate] 【发布时间】:2011-07-01 12:41:46 【问题描述】:

我需要在我的表中添加正确的 index 并需要一些帮助。

我很困惑,需要澄清几点:

我应该为non-int 列使用索引吗?为什么/为什么不

我已经阅读了很多关于 clusterednon-clustered 索引的内容,但我仍然无法决定何时使用其中一个。一个很好的例子会帮助我和许多其他开发人员。

我知道我不应该对经常更新的列或表使用索引。在进入测试阶段之前我还应该注意什么以及如何知道一切都很好?

【问题讨论】:

一个项目的开始,绝对是最“冲”的阶段。这是您为数据库奠定基础的地方。任何建立在糟糕基础上的东西都会以某种方式失败。现在慢慢来,稍后再赶;-) 【参考方案1】:

聚集索引改变了行的存储方式。当您为一列(或多列)创建聚集索引时,SQL Server 按该列对表的行进行排序。它就像一本字典,整本书中的所有单词都按字母顺序排列。

另一方面,非聚集索引不会改变行在表中的存储方式。它在表中创建一个完全不同的对象,其中包含选择用于索引的列和指向包含数据的表行的指针。它就像一本书最后几页的索引,其中的关键字被排序并包含书籍材料的页码,以便更快地参考。

【讨论】:

【参考方案2】:

比非集群读取更快,因为数据是按索引顺序物理存储的 我们每个表只能创建一个。(集群索引)

插入和更新操作比集群索引更快。 我们可以创建n个非聚集索引。

【讨论】:

【参考方案3】:

非聚集索引与聚集索引的比较与示例

作为非聚集索引的示例,假设我们在 EmployeeID 列上有一个非聚集索引。非聚集索引将存储

员工编号

AND 指向 Employee 表中实际存储该值的行的指针。但另一方面,聚集索引实际上会存储特定 EmployeeID 的行数据——因此,如果您正在运行查找 EmployeeID 为 15 的查询,则来自表中其他列的数据,例如

员工姓名、员工地址等

。实际上都将存储在聚集索引本身的叶子节点中。

这意味着使用非聚集索引需要额外的工作来跟随指向表中行的指针以检索任何其他所需的值,而不是聚集索引只能直接访问该行,因为它正在以与聚集索引本身相同的顺序存储。因此,从聚集索引读取通常比从非聚集索引读取要快。

【讨论】:

除了最后一句话外,一个不错的解释。从聚集索引读取很少比从非聚集索引读取快,因为 CL 索引通常比同一张表上的任何 NC 索引大得多,而且永远不会小。这就是为什么查询优化器通常会在可能的情况下选择 NC 索引而不是 CL 索引 - 特别是对于不需要书签查找的“覆盖”查询。 这是否意味着当我们有数据更新频繁的用例时,每次更新数据时SQL都需要更新索引?并且在执行更新时它会减慢 SQL 的速度吗? (当然我说的是庞大的数据集)【参考方案4】:

一般来说,在将要(很多)用于搜索表的列上使用索引,例如主键(默认情况下具有聚集索引)。例如,如果您有查询(在伪代码中)

SELECT * FROM FOO WHERE FOO.BAR = 2

您可能想在 FOO.BAR 上放置一个索引。应该在将用于排序的列上使用聚集索引。聚集索引用于对磁盘上的行进行排序,因此每个表只能有一个。例如,如果您有查询

SELECT * FROM FOO ORDER BY FOO.BAR ASCENDING

您可能需要考虑在 FOO.BAR 上使用聚集索引。

可能最重要的考虑因素是您的查询花费了多少时间。如果查询不需要太多时间或不经常使用,则可能不值得添加索引。与往常一样,首先配置文件,然后进行优化。 SQL Server Studio 可以为您提供优化的建议,MSDN 有一些您可能会觉得有用的信息1

【讨论】:

我很困惑,pk不是聚集索引吗?而且我知道我只能在表中有 1 个。你的回答没有意义。 @pabuc:PK 是聚集索引默认情况下 - 但它不是必须是。您可以将 PK 放在非聚集的一列上,而另一列构成聚集索引 @marc_s 感谢您解决这个问题。我已经更新了答案以反映这一点。【参考方案5】:

你真的需要把两个问题分开:

1) 主键 是一种逻辑结构 - 候选键之一,可唯一且可靠地标识表中的每一行。这可以是任何东西,真的 - 一个 INT、一个 GUID、一个字符串 - 选择对你的场景最有意义的东西。

2) clustering key(在表上定义“聚集索引”的一列或多列)-这是一个与存储相关的物理事物,这里,小型、稳定、不断增长的数据类型是您的最佳选择 - INT 或 BIGINT 作为您的默认选项。

默认情况下,SQL Server 表上的主键也用作集群键 - 但不必这样!

我要应用的一条经验法则是:任何“常规”表(用于存储数据的表,即查找表等)都应该有一个集群键。没有集群键真的没有意义。实际上,与普遍认为的相反,拥有集群键实际上加速了所有常见操作 - 甚至插入和删除(因为表组织不同并且通常比使用 heap - 没有集群的表键)。

Kimberly Tripp, the Queen of Indexing 有很多优秀的文章,主题是为什么要有一个集群键,以及什么样的列最适合用作集群键。由于每个表只能获得一个,因此选择正确集群键至关重要 - 而不仅仅是任何集群键。

GUIDs as PRIMARY KEY and/or clustered key The clustered index debate continues Ever-increasing clustering key - the Clustered Index Debate..........again! Disk space is cheap - that's not the point!

马克

【讨论】:

未标记为主键的标识列怎么办?是集群的吗? @ProgrammerIT: no - IDENTITY 列仅此而已 - 系统生成的值。没有别的了。【参考方案6】:

您应该使用索引来提高 SQL 服务器的性能。通常这意味着用于在表中查找行的列已编入索引。

聚集索引使 SQL Server 根据索引顺序对磁盘上的行进行排序。这意味着如果您按照聚集索引的顺序访问数据,那么数据将以正确的顺序出现在磁盘上。但是,如果具有聚集索引的列经常更改,那么行将在磁盘上移动,从而导致开销——这通常不是一个好主意。

索引太多也不好。他们需要维护。所以从明显的开始,然后分析你错过哪些并且会从中受益的。您从一开始就不需要它们,它们可以稍后添加。

索引时可以使用大多数列数据类型,但索引小列比索引大列更好。此外,通常在列组上创建索引(例如国家 + 城市 + 街道)。

此外,在您的表中有相当多的数据之前,您不会注意到性能问题。另一件要考虑的事情是 SQL 服务器需要统计信息才能以正确的方式进行查询优化,因此请确保您确实生成了它。

【讨论】:

2 点。 . .默认情况下,当您向表添加主键时,它是一个聚集索引。其次,您只能拥有 1 个聚集索引。

以上是关于聚集索引和非聚集索引之间的区别 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

聚集索引和非聚集索引有啥区别?

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

聚集索引和唯一索引的区别是啥?

SqlServer中创建非聚集索引和非聚集索引

聚集索引和非聚集索引区别

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