外键列上的聚簇索引是否会增加连接性能与非群集?

时间:2010-03-11 22:02:17

标签: sql performance join foreign-keys clustered-index

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

考虑到我只关心那个选择加入而没有别的选择,我猜错了吗?

5 个答案:

答案 0 :(得分:9)

在绝对中讨论此类问题并不是很有用。

始终是个案情况!

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

假设在JOIN中使用的密钥是聚簇索引的密钥,在单个读取中[无论是从索引查找还是从扫描或部分扫描,无关紧要],您将得到整行(记录)

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

有时人们会获得聚集索引的等效优势,使用covering index,即具有所需键序列的索引,然后是我们感兴趣的列值。就像聚簇索引一样,覆盖索引不需要间接到基础表。实际上,覆盖指数可能比聚集指数略微更有效,因为它更小 但是,就像聚簇索引一样,除了存储开销之外,在INSERT(和DELETE或UPDATE)查询期间还有与任何额外索引相关的性能成本。

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

要做出关于索引结构的明智决策,需要

  • 了解各种索引类型(和堆)的工作方式 (而且,顺便说一句,这在SQL实现之间有所不同)
  • 可以很好地了解手头数据库的统计资料:
    哪些是大表,哪些是关系,关系的平均/最大基数是什么,数据库的典型增长率是什么等。
  • 能够很好地了解将要使用/查询数据库的方式

然后,只有这样,才能对有兴趣[或缺乏]的人进行有根据的猜测,以获得给定的聚集索引。

答案 1 :(得分:3)

我会问其他问题:将聚簇索引放在外键列上只是为了加速单个JOIN是明智的吗?它可能会有所帮助,但是......付出代价!

聚簇索引使每个操作的表更快。是!确实如此。有关背景信息,请参阅Kim Tripp的优秀The Clustered Index Debate continues。她还提到了她对聚集索引的主要标准:

  • 静态(永不改变)
  • 独特
  • 如果可能的话:不断增加

INT IDENTITY完美地实现了这一点 - GUID没有。有关详细背景信息,请参阅GUID's as Primary Key

为什么要缩小?因为聚簇键被添加到同一个表中每个非聚集索引的每个索引页面上(为了能够实际查找数据行) , 如果需要的话)。您不希望在群集密钥中使用VARCHAR(200)....

为什么是唯一的?参见上文 - 群集密钥是SQL Server用于唯一查找数据行的项和机制。它必须是独一无二的。如果您选择一个非唯一的群集键,SQL Server本身将为您的键添加一个4字节的唯一键。小心一点!

所以这些是我的标准 - 将您的聚类键放在一个狭窄,稳定,独特,希望不断增加的专栏中。如果您的外键列与那些匹配 - 完美!

但是,在任何情况下,我都会将我的群集密钥放在一个宽的甚至复合的外键上。请记住:集群密钥的值正被添加到该表上的每个非聚集索引条目中!如果您有10个非聚集索引,表中有100'000行 - 这是一百万个条目。无论是4字节整数还是200字节VARCHAR - HUGE,它都会产生巨大的差异。而不只是在磁盘上 - 也在服务器内存中。仔细考虑如何制作聚簇索引!

SQL Server可能需要添加一个uniquifier - 使事情变得更糟。如果值会发生变化,SQL Server将不得不在整个地方进行大量的簿记和更新。

简而言之:

  • 在你的外键上放一个索引绝对是一个好主意 - 一直这样做!
  • 我会非常小心地将其作为聚集索引。首先,你只得到一个聚集索引,那么你要选择哪种FK关系?并且不要将聚类密钥放在广泛且不断变化的列上

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

这取决于数据库的实现。

对于SQL Server,聚簇索引是一种数据结构,其中数据存储为页面,并且存在B树并作为单独的数据结构存储。您获得快速性能的原因是,您可以快速访问链的 start ,范围是一个易于链接的链接列表。

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

请参阅有关Clustered Index Structures的文档。

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

答案 4 :(得分:0)

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