聚集索引碎片与包含列碎片的索引

Dir*_*oer 7 performance index sql-server clustered-index index-tuning

我有一个相对较大的表(对我来说)有 4000 万行,预计在两周内(在活动期间)会增长到 80 到 1.2 亿行。

Tip
--------------
Id          int (clustered index)
UserId      int
TipIndex    smallint
Value       binary(8)
LastChanged datetime2(3)
Run Code Online (Sandbox Code Playgroud)
  • 每个用户都有 1 到 400 个提示,这些提示将在此期间随机插入
  • UserId + TipIndex 是唯一的
  • 我从不直接在身份密钥 (Id) 上查询 Tips
  • 我查询 UserId 的次数有 99%
  • 我需要所有列
  • 我经常查询 1 个 UserId(每个页面视图),有时查询 10.000 个批次的统计信息
  • 这是在此期间的高流量站点,它应该能够每分钟处理 30.000 次 UserId 查询
  • Id 目前是我的聚集索引,因为我读到它导致最少的碎片化。

所以我托管在 SQL Azure 上,Azure 已经建议添加一个包含列的索引。我总是犹豫是否使用 UserId,TipIndex 作为聚集索引,因为 Tips 会随机添加。这意味着我害怕巨大的碎片问题等。

我的问题:

  • 包含列的索引没有完全相同的问题吗?
  • 包含列的表是否与具有相同碎片问题的“影子表”相同?
  • 我应该迁移以使用 UserId、TipIndex 作为 ClusteredIndex 而不是 Id?
  • 如何防止碎片化?

我知道最终答案总是“取决于”或者我应该衡量它。但由于我是一名单独的开发人员并且没有很多资源,我希望有更多经验的人对此有直觉,所以我的第一次尝试有更高的机会朝着正确的方向前进。

Rob*_*ley 7

你的问题:

包含列的索引没有完全相同的问题吗?

是的。

包含列的表是否与具有相同碎片问题的“影子表”相同?

是的

我应该迁移以使用 UserId、TipIndex 作为 ClusteredIndex 而不是 Id?

我愿意,是的。

如何防止碎片化?

有几种不同类型的碎片需要考虑。一种情况是,您只使用了部分页面,因为您进行了页面拆分。如果您有很多插入物,就会发生这种情况。不要压力太大。另一种是当您的页面的后续页面处于不同程度时。再说一次,我不会太担心。如果您的数据主要位于缓冲区缓存中,那么它是否跨区移动并不重要。

所以……不用太担心。但是不要费心以一种您实际上不会查询它的方式来获得完整的数据副本。

  • 给先生点赞。我想,我们同时发布了答案,很高兴看到我的观点与您这样的专家相符:) (2认同)
  • 你的回答也很好。我很确定“影子表”只是指包含所有列的索引。 (2认同)

Lea*_*min 6

看来你太在意碎片化了,只要你定期更新统计,碎片化应该不会对你的性能造成太大的困扰。您可以在Brent Ozar 先生分享的视频以及此处的另一个页面上阅读有关此的更多详细信息。让我试着一一回答你的问题:

包含列的索引没有完全相同的问题吗?

包含列中的索引或者是键列,差别不大。键列将成为 B 树的一部分,而包含列不是,但是当您执行任何插入/更新/删除操作时,这将产生与这些列需要更新/插入/删除相同的费用。

包含列的表是否与具有相同碎片问题的“影子表”相同?

不太确定你所说的影子表是什么意思,如果你在这里指的是基表,那么是的,就碎片而言,你会遇到同样的问题。

我应该迁移以使用 UserId、TipIndex 作为 ClusteredIndex 而不是 Id?

根据您的陈述 - “我在 UserId 上查询的次数为 99%”,这是主键聚集列的一个很好的候选者。由于您不会非常频繁地使用 Id 列,因此我认为使用 UserId 和 TipIndex 形式的复合主聚集键没有任何问题。就索引的大小而言,它与Id(int --> 4 byte) 加上tinyint 类型的附加列(1 字节) 一样好。

请理解,聚簇键只不过是逻辑存储的数据顺序,与非聚簇键不同,它没有任何物理存在。

如何防止碎片化?

我会说更新统计信息应该优先考虑而不是碎片化。您可以使用Ola Hallengren 的世界各地许多 DBA使用的维护脚本。您可以根据您的要求每周或每两周安排一次。

希望这可以帮助。

  • 聚集索引键的大小取决于聚集索引的非叶级别的数据量,以及需要包含在非聚集索引中和非唯一性的叶级别的数据量非聚集索引。但是,如果您总是以相同的方式查询数据,那么更大的好处是没有您不需要的数据的第二个副本。 (2认同)