6

在许多地方,建议在使用 BETWEEN 语句选择行范围时更好地利用聚集索引。当我以使用此聚集索引的方式选择通过外键字段连接时,我想,集群化也应该有所帮助,因为即使它们都具有相同的聚集键值并且未使用 BETWEEN,也会选择行的范围。

考虑到我只关心那个有 join 而没有别的选择,我的猜测是不是错了?

4

5 回答 5

10

绝对地讨论这类问题并不是很有用。

它总是一个个案的情况!

本质上,通过聚集索引进行访问可以节省一个间接时间。

假设在 JOIN 中使用的键是聚集索引的键,在单次读取中[无论是从索引搜索还是从扫描或部分扫描,都没有关系],您将获得整行(记录)。

聚集索引的一个问题是每个表只能得到一个。因此,您需要明智地使用它。实际上,在某些情况下,由于 INSERT 开销和碎片(取决于键和新键的顺序等),根本不使用任何聚集索引甚至更明智。

有时人们会获得与聚集索引相同的好处,它具有覆盖索引,即具有所需键序列的索引,后跟我们感兴趣的列值。就像聚集索引一样,覆盖索引没有需要对基础表的间接访问。实际上,覆盖索引可能比聚集索引更有效,因为它更小。
但是,就像聚集索引一样,除了存储开销之外,在 INSERT(和 DELETE 或 UPDATE)查询期间,任何额外的索引都会产生性能成本

而且,是的,如其他答案所示,用于聚集索引的键的“外键性”与索引的性能完全无关。FK 是旨在简化数据库完整性维护的约束,但底层字段(列)与表中的任何其他字段一样。

要对索引结构做出明智的决定,需要

  • 了解各种索引类型(和堆)的工作方式
    (顺便说一句,这在 SQL 实现之间有所不同)
  • 对现有数据库的统计概况有一个很好的了解:
    哪些是大表,哪些是关系,关系的平均/最大基数是多少,数据库的典型增长率是多少等。
  • 深入了解数据库将被使用/查询的方式

只有到那时,人们才能对拥有给定聚集索引的兴趣 [或缺乏兴趣] 做出有根据的猜测。

于 2010-03-11T22:24:32.267 回答
3

我会问别的问题:将聚集索引放在外键列上只是为了加快单个 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 关系呢?并且不要将聚类键放在一个宽且不断变化的列上
于 2010-03-12T06:18:01.540 回答
2

FK 列上的索引将有助于 JOIN,因为索引本身是有序的:聚集只是意味着磁盘(叶)上的数据是有序的,而不是 B 树。

如果将其更改为覆盖索引,则聚集与非聚集无关。重要的是要有一个有用的索引。

于 2010-03-11T22:11:43.900 回答
1

这取决于数据库的实现。

对于 SQL Server,聚集索引是一种数据结构,其中数据存储为页面,并且存在 B 树并存储为单独的数据结构。您获得快速性能的原因是您可以快速到达链的开头,并且范围是一个易于遵循的链表。

非聚集索引是一种数据结构,它包含指向实际记录的指针以及不同的关注点。

请参阅有关聚簇索引结构的文档。

索引对外键关系没有帮助,但由于“覆盖”索引的概念,它会有所帮助。如果您的 WHERE 子句包含基于索引的约束。它将能够更快地生成返回的数据集。这就是性能的来源。

于 2010-03-11T22:11:51.997 回答
0

如果您在集群中按顺序选择数据,通常会获得性能提升。此外,它完全取决于表(数据)的大小和 between 语句中的条件。

于 2010-03-11T22:08:05.997 回答