聚集索引 vs 覆盖索引

5
考虑在 SQL Server 2008 中的以下表格:
LanguageCode  varchar(10)
Language      nvarchar(50)

LanguageCode参与了关系,因此我无法创建包含两列(LanguageCode和Language)的主键索引。

如果我在LanguageCode上放置一个主聚集键,当然我不能在该索引(覆盖索引)中包含Language。这意味着我必须为Language创建第二个索引,否则就会有重复值(还会强制进行表扫描以检索其值)。

此外,微软的文档(以及专家们)指出,表应该理想情况下具有聚集索引。

在这种情况下,非聚集覆盖索引(LanguageCode, Language)不仅可以确保Language是唯一的,而且可以避免表扫描。然而,没有"理想的"聚集索引。

这是那些没有聚集索引实际上是理想的情况之一吗?

根据反馈进行编辑:

我想运行的唯一查询是:

SELECT Language, LanguageCode FROM Languages where Language="EN"

你的语言表是否会参与到连接操作中? - Quassnoi
@Quassnoi 是的 - 它将根据 LanguageCode 进行连接(匹配其关系)。 - IamIC
3个回答

7

按照定义,聚集索引覆盖所有列。

如果在 LanguageCode 上创建一个 PRIMARY KEY CLUSTERED ,并在 Language 上创建一个 UNIQUE INDEX,则可以通过单次查找搜索语言代码和名称,并且还可以使 Language 列唯一。


1
@Ian:你不能使用单个索引来独立查找两个不同的列。索引依赖于排序,而你无法同时对两列进行排序。 - Quassnoi
1
@Ian:在Language上搜索还是搜索并加入Language?由于外键引用了LanguageCode,所以似乎你也需要在其上进行连接。 - Quassnoi
@Quassnoi,连接操作基于LanguageCode字段,查找操作基于Language字段。 - IamIC
@Quassnoi 只需记住,连接是在主键上进行的。因此,索引 #2 只会给我带来唯一性,没有其他好处(在这种情况下)。 - IamIC
1
@IanC:是的,但如果没有a = ?,它就不会。我相信您有两种不同类型的查询:第一种类型搜索用户提供的LanguageName,第二种类型连接到LanguageCode。您需要为这些查询创建两个不同的索引。 - Quassnoi
显示剩余7条评论

5
  1. 在聚集索引中不需要包含列。由于聚集索引就是“数据”,所有列都会自动包含。

  2. 如果您需要通过语言进行搜索和/或确保其唯一性,则一定要在其上创建额外的索引。


谢谢 - 我理解你的观点,聚集索引就是数据。我查询了SQL Server的存储系统。顺便说一句,我想知道这对多少数据库适用。 - IamIC
@IanC:对于支持群集索引的每个数据库来说,这都是正确的。其中主要的有 SQL ServerOracle(称为索引组织表)和 InnoDBMySQL的存储引擎之一)。 - Quassnoi
@Quassnoi,那PostgreSQL呢?我知道Caché使用了不同的系统。除了价格标签之外,它仍然是我最喜欢的数据库。 - IamIC
@Ian:PostgreSQL不支持聚集索引。 - Quassnoi
@Quassnoi 有趣。尽管基准测试的价值有限,但它似乎在基准测试中表现良好。 - IamIC

0

根据主题的性质(我猜测是人类使用的语言),索引以提高性能将是无关紧要的。如果您有100种语言,每行占用120个字节(伪分解varchar标题,null位掩码等),则会有12,000个字节的数据,适合两个8k页面。 SQL不会在任何小于此大小的内容上使用索引,它将只扫描整个表(2页)并进行暴力搜索,所需时间少于可以轻松测量的时间。

确保唯一性的索引,当然,我经常这样做。但是对于性能,直到达到3页(或4页),它都没有关系。(如果您正在跟踪编程语言,这将发生,因为每周左右会有十几种新语言。)


2
这完全取决于 @op 将使用的查询。请参见此处:http://explainextended.com/2009/06/22/indexing-tiny-tables/ - Quassnoi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接