在许多地方,建议在使用BETWEEN语句选择行范围时更好地利用聚簇索引。当我选择使用外键字段以使用此聚簇索引的方式连接时,我想,该聚类应该也有帮助,因为即使它们都具有相同的聚簇键值并且未使用BETWEEN,也会选择行范围。 / p>
考虑到我只关心那个选择加入而没有别的选择,我猜错了吗?
答案 0 :(得分:9)
在绝对中讨论此类问题并不是很有用。
基本上,通过聚集索引进行访问可以节省一个间接,句号。
假设在JOIN中使用的密钥是聚簇索引的密钥,在单个读取中[无论是从索引查找还是从扫描或部分扫描,无关紧要],您将得到整行(记录)
聚簇索引的一个问题是,每个表只能获得一个。因此,您需要明智地使用它。实际上,在某些情况下,由于INSERT开销和碎片(取决于密钥和新密钥的顺序等),根本不使用任何聚簇索引更为明智。
有时人们会获得聚集索引的等效优势,使用covering index,即具有所需键序列的索引,然后是我们感兴趣的列值。就像聚簇索引一样,覆盖索引不需要间接到基础表。实际上,覆盖指数可能比聚集指数略微更有效,因为它更小 但是,就像聚簇索引一样,除了存储开销之外,在INSERT(和DELETE或UPDATE)查询期间还有与任何额外索引相关的性能成本。
而且,是的,正如其他答案中所指出的,用于聚集索引的密钥的“外键密钥”对索引的性能完全没有影响。 FK是旨在简化数据库完整性维护的约束,但底层字段(列)与表中的任何其他字段一样。
要做出关于索引结构的明智决策,需要
然后,只有这样,才能对有兴趣[或缺乏]的人进行有根据的猜测,以获得给定的聚集索引。
答案 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将不得不在整个地方进行大量的簿记和更新。
简而言之:
答案 2 :(得分:2)
FK列上的索引将帮助JOIN,因为索引本身是有序的:clustered只是意味着磁盘(叶子)上的数据是有序的,而不是B树。
如果将其更改为覆盖索引,则群集与非群集无关。重要的是要有一个有用的索引。
答案 3 :(得分:1)
这取决于数据库的实现。
对于SQL Server,聚簇索引是一种数据结构,其中数据存储为页面,并且存在B树并作为单独的数据结构存储。您获得快速性能的原因是,您可以快速访问链的 start ,范围是一个易于链接的链接列表。
非群集索引是一种数据结构,包含指向实际记录的指针,以及不同的关注点。
请参阅有关Clustered Index Structures的文档。
索引对外键关系没有帮助,但由于“覆盖”索引的概念,它会有所帮助。如果WHERE子句包含基于索引的约束。它将能够更快地生成返回的数据集。这就是性能的来源。
答案 4 :(得分:0)
如果要在群集中按顺序选择数据,通常会获得性能提升。此外,它完全取决于表(数据)的大小和中间语句中的条件。