在许多地方,建议在使用 BETWEEN 语句选择行范围时更好地利用聚集索引。当我以使用此聚集索引的方式选择通过外键字段连接时,我想,集群化也应该有所帮助,因为即使它们都具有相同的聚集键值并且未使用 BETWEEN,也会选择行的范围。
考虑到我只关心那个有 join 而没有别的选择,我的猜测是不是错了?
在许多地方,建议在使用 BETWEEN 语句选择行范围时更好地利用聚集索引。当我以使用此聚集索引的方式选择通过外键字段连接时,我想,集群化也应该有所帮助,因为即使它们都具有相同的聚集键值并且未使用 BETWEEN,也会选择行的范围。
考虑到我只关心那个有 join 而没有别的选择,我的猜测是不是错了?
绝对地讨论这类问题并不是很有用。
本质上,通过聚集索引进行访问可以节省一个间接时间。
假设在 JOIN 中使用的键是聚集索引的键,在单次读取中[无论是从索引搜索还是从扫描或部分扫描,都没有关系],您将获得整行(记录)。
聚集索引的一个问题是每个表只能得到一个。因此,您需要明智地使用它。实际上,在某些情况下,由于 INSERT 开销和碎片(取决于键和新键的顺序等),根本不使用任何聚集索引甚至更明智。
有时人们会获得与聚集索引相同的好处,它具有覆盖索引,即具有所需键序列的索引,后跟我们感兴趣的列值。就像聚集索引一样,覆盖索引没有需要对基础表的间接访问。实际上,覆盖索引可能比聚集索引更有效,因为它更小。
但是,就像聚集索引一样,除了存储开销之外,在 INSERT(和 DELETE 或 UPDATE)查询期间,任何额外的索引都会产生性能成本。
而且,是的,如其他答案所示,用于聚集索引的键的“外键性”与索引的性能完全无关。FK 是旨在简化数据库完整性维护的约束,但底层字段(列)与表中的任何其他字段一样。
要对索引结构做出明智的决定,需要
只有到那时,人们才能对拥有给定聚集索引的兴趣 [或缺乏兴趣] 做出有根据的猜测。
我会问别的问题:将聚集索引放在外键列上只是为了加快单个 JOIN 是否明智?它可能会有所帮助,但是……要付出代价!
对于每个操作,聚集索引使表更快。是的!确实如此。有关背景信息,请参阅 Kim Tripp 的优秀聚集索引辩论继续。她还提到了她对聚集索引的主要标准:
INT IDENTITY 完美地实现了这一点 - GUID 没有。有关广泛的背景信息,请参阅GUID 作为主键。
为什么窄?因为聚集键被添加到同一张表上每个非聚集索引的每个索引页(如果需要,以便能够实际查找数据行)。你不想在你的集群键中有 VARCHAR(200)....
为什么独一无二??见上文 - 群集键是 SQL Server 用于唯一查找数据行的项和机制。它必须是独一无二的。如果您选择一个非唯一的集群键,SQL Server 本身会为您的键添加一个 4 字节的唯一符。小心那个!
所以这些是我的标准——把你的聚类键放在一个狭窄的、稳定的、独特的、希望不断增加的列上。如果您的外键列与那些匹配 - 完美!
但是,在任何情况下,我都不会将我的集群键放在宽外键甚至复合外键上。请记住:聚集键的值被添加到该表上的每个非聚集索引条目中!如果您有 10 个非聚集索引,表中有 100'000 行 - 那就是一百万个条目。无论是 4 字节整数还是 200 字节 VARCHAR - HUGE,都会产生巨大的差异。不仅在磁盘上 - 在服务器内存中也是如此。非常非常仔细地考虑如何制作你的聚集索引!
SQL Server 可能需要添加一个 uniquifier - 使事情变得更糟。如果这些值会发生变化,SQL Server 将不得不在各处进行大量的记账和更新。
简而言之:
FK 列上的索引将有助于 JOIN,因为索引本身是有序的:聚集只是意味着磁盘(叶)上的数据是有序的,而不是 B 树。
如果将其更改为覆盖索引,则聚集与非聚集无关。重要的是要有一个有用的索引。
这取决于数据库的实现。
对于 SQL Server,聚集索引是一种数据结构,其中数据存储为页面,并且存在 B 树并存储为单独的数据结构。您获得快速性能的原因是您可以快速到达链的开头,并且范围是一个易于遵循的链表。
非聚集索引是一种数据结构,它包含指向实际记录的指针以及不同的关注点。
请参阅有关聚簇索引结构的文档。
索引对外键关系没有帮助,但由于“覆盖”索引的概念,它会有所帮助。如果您的 WHERE 子句包含基于索引的约束。它将能够更快地生成返回的数据集。这就是性能的来源。
如果您在集群中按顺序选择数据,通常会获得性能提升。此外,它完全取决于表(数据)的大小和 between 语句中的条件。