【问题标题】:Clustered and nonclustered indexes performance聚集和非聚集索引性能
【发布时间】:2011-10-12 08:12:54
【问题描述】:

我有一个巨大的表(约 1000 万行),在随机唯一标识符列上具有聚集的 PK。如果还没有具有相同 pk 的行,我对该表执行的大多数操作是插入一个新行。 (为了提高它的性能,我使用 IGNORE_DUP_KEY = ON 选项)

我的问题是

我可以完全摆脱这张表上的聚集索引吗?我的意思是当我在具有聚集索引的表中插入一行时,它应该重新排列数据。是否最好删除聚集索引并在该列上创建非聚集索引以避免数据重新排列?

我无法在实时数据库上进行实验,因为如果性能下降会很头疼。在测试数据库上,我只能在聚集索引的情况下看到“聚集索引插入 100%”,在非聚集索引的情况下,在非聚集索引中看到“表插入”+ 一些查找操作。

提前致谢

【问题讨论】:

  • 好吧,将 GUID 作为聚集索引并不是一个很好的选择,尤其是在大表上 - 请参阅 Kim Tripp: GUID as a primary key。尝试使用 INT IDENTITY 作为您的集群键 - 应该会有很大的不同!但是不要完全摆脱你的集群键 - 堆甚至更慢......
  • 同意 marc_s:你会看到很多页面拆分...
  • 您是否确实进行了任何测量以表明聚集索引会导致插入性能问题?如果你只是猜测,我建议你先测量,遵循等待和队列方法:technet.microsoft.com/en-us/library/cc966413.aspx

标签: sql-server performance clustered-index


【解决方案1】:

GUID 似乎是您的主键的自然选择 - 如果您真的必须,您可能会争辩将其用作表的主键。我强烈建议不要这样做是使用 GUID 列作为 集群键,SQL Server 默认会这样做,除非你明确告诉它不要这样做。 p>

你真的需要把两个问题分开:

1) 主键 是一种逻辑结构 - 候选键之一,可唯一且可靠地标识表中的每一行。这可以是任何东西,真的 - 一个 INT、一个 GUID、一个字符串 - 选择对你的场景最有意义的东西。

2) clustering key(在表上定义“聚集索引”的一列或多列)-这是一个与存储相关的物理事物,这里,一个小的、稳定的、不断增长的数据类型是您的最佳选择 - INTBIGINT 作为您的默认选项。

默认情况下,SQL Server 表上的主键也用作集群键 - 但不需要这样!将以前基于 GUID 的主键/集群键分解为两个单独的键 - GUID 上的主(逻辑)键和单独 INT IDENTITY(1,1) 上的集群(排序)键时,我个人看到了巨大的性能提升柱子。

正如Kimberly Tripp - 索引女王 - 和其他人已经多次声明的那样 - 作为集群键的 GUID 并不是最优的,因为由于它的随机性,它会导致大量页面和索引碎片,并一般表现不佳。

是的,我知道 - 在 SQL Server 2005 及更高版本中有 newsequentialid() - 但即使这样也不是真正的完全顺序的,因此也会遇到与 GUID 相同的问题 - 只是不太突出。

还有一个需要考虑的问题:表上的聚簇键也将添加到表上每个非聚簇索引的每个条目中 - 因此您确实希望确保它尽可能小.通常,具有 2 亿以上行的 INT 对于绝大多数表来说应该足够了 - 与作为集群键的 GUID 相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。

快速计算 - 使用 INT 与 GUID 作为主键和聚类键:

  • 具有 1'000'000 行的基表(3.8 MB 与 15.26 MB)
  • 6 个非聚集索引(22.89 MB 与 91.55 MB)

总计:25 MB vs. 106 MB - 这只是在一张桌子上!

更多值得深思的东西 - Kimberly Tripp 的优秀作品 - 阅读,再阅读,消化!这是 SQL Server 索引的福音,真的。正如她在她的“The Clustered Index Debate Contiues”中所展示的那样,拥有一个好的集群键(而不是没有或坏的)确实可以加速几乎所有的数据库操作!这是一个好主意 - 但它必须是一个好的聚类键......

马克

【讨论】:

  • 感谢马克非常明确的解释!我需要一些时间考虑一下,然后我会写下结果。
  • 我们可以使用日期时间列作为新的聚集键吗?在该表中有一列“CreatedDate”,有时我们需要获取 max(CreatedDate)。它是连续的,永远不会改变。
  • @Ruslan:你可以——但你不应该——至少不是一个人。不能保证 DateTime 是唯一的 - 如果不是,SQL Server 将为每个条目添加 4 个字节......不推荐......INT IDENTITY 确实是最好的选择 - 可能与 DateTime 一起(但我我自己不会将 DateTime 列放入集群键中)
猜你喜欢
  • 2013-08-07
  • 2016-09-05
  • 2016-01-05
  • 1970-01-01
  • 2021-01-14
  • 2023-03-23
  • 2011-07-02
  • 2011-03-24
相关资源
最近更新 更多