【问题标题】:Clustered vs covering index聚集索引与覆盖索引
【发布时间】:2011-05-09 07:00:41
【问题描述】:

考虑一下 SQL Server 2008 中的下表:

LanguageCode  varchar(10)
Language      nvarchar(50)

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

如果我在 LanguageCode 上放置一个主聚集键,当然我不能在索引中包含 Language(覆盖索引)。这意味着我将不得不为 Language 创建第二个索引,否则会冒重复的风险(加上强制表扫描以检索其值)。

此外,MS 的文档(以及该主题的专家)表明,表应该理想地具有聚集索引。

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

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

根据反馈进行修改:

我希望运行的唯一查询是:

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

【问题讨论】:

  • 您的语言表会参与联接吗?
  • @Quassnoi 是的 - 它将加入 LanguageCode(匹配其关系)

标签: sql-server database-design indexing


【解决方案1】:

根据定义,聚集索引涵盖所有列。

如果您在LanguageCode 上创建PRIMARY KEY CLUSTERED 并在Language 上创建UNIQUE INDEX,它将允许您通过单次查找同时通过其代码和名称来搜索语言,此外,使Language 独一无二。

【讨论】:

  • @Quassnoi 这就是我最初所做的。昨天在您的帮助下,我一直在浏览数据库并优化其索引。我试图在这里摆脱 1 个索引,因为实际上,我只会按语言搜索。
  • @Ian:您不能使用单个索引来独立查找两个不同的列。索引依赖于排序,您不能同时对两列进行排序。
  • @Ian:搜索Language 还是搜索并加入Language?由于LanguageCode 是由外键引用的,因此您似乎也想加入它。
  • @Quassnoi 加入在 LanguageCode 上,查找在 Language 上。
  • @IanC:是的,它会,但没有a = ? 它不会。我相信你有两种不同类型的查询:第一种类型搜索用户提供的LanguageName,第二种类型加入LanguageCode。这些查询需要两个不同的索引。
【解决方案2】:
  1. 不需要在聚集索引中包含列。由于聚集索引是“数据”,所有列都会自动包含在内。

  2. 如果您需要按语言搜索和/或确保其唯一性,那么一定要在其上创建一个附加索引。

【讨论】:

  • 谢谢 - 我明白你的意思了。聚集索引是数据。我查找了 SQL Server 的存储系统。作为旁注,我想知道这适用于多少数据库。
  • @IanC:每个支持聚集索引的数据库都是如此。其中主要有SQL ServerOracle(称为索引组织表)和InnoDBMySQL 的存储引擎之一)。
  • @Quassnoi PostgreSQL 怎么样?我知道 Caché 使用不同的系统。它仍然是我的最爱。 DB,除了价格标签。
  • @Ian:PostgreSQL 不支持聚集索引。
  • @Quassnoi 有趣。不过,它在基准测试中似乎还算不错(就它们的价值而言)。
【解决方案3】:

基于主题的性质(我猜是人类所说的语言),索引性能将是无关紧要的。如果您有 100 种语言,并且每行占用 120 个字节(在 varchar 标头、空位掩码等中进行伪因子分解),那么您将拥有 12,000 个字节的数据,这些数据适合两个 8k 页。 SQL 不会费心在任何小的东西上使用索引,它只会对整个东西(2 页)进行表扫描并暴力破解它,所需的时间比可以轻松测量的要少。

索引以确保唯一性,当然,我一直这样做。但是为了性能,直到你打到 3 页(或者是 4 页),这都没关系。 (如果您正在跟踪编程语言,就会发生这种情况,因为每周左右都会有十几个新语言。)

【讨论】:

猜你喜欢
  • 2011-02-19
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 2018-08-04
  • 2021-09-07
  • 1970-01-01
  • 2020-08-04
  • 2011-04-23
相关资源
最近更新 更多