Uniqueidentifier PK:SQL Server堆是正确的选择吗?

时间:2009-08-17 07:49:09

标签: sql sql-server performance sql-server-2008 indexing

行。我已经在这里和那里读过关​​于SQL Server堆的东西,但没有什么太明确的真正指导我。我将尝试衡量绩效,但希望能就我应该研究的内容提供一些指导。这是SQL Server 2008 Enterprise。以下是表格:

工作

  • JobID(PK,GUID,外部生成)
  • StartDate(datetime2)
  • AccountId
  • 多个会计字段,主要是小数和bigints

JobSteps

  • JobStepID(PK,GUID,外部生成)
  • JobID FK
  • 开始日期
  • 多个会计字段,主要是小数和bigints

用法:大量插入(数百/秒),每个作业通常为1个JobStep。估计每月可能有100-200M行。根本没有更新,唯一的删除来自3个月以前的归档数据。

对数据执行~10次查询/秒。有些人将JobSteps加入乔布斯,有些人只看乔布斯。几乎所有查询都在StartDate上,其中大多数包括AccountId和一些其他会计字段(我们有它们的索引)。查询非常简单 - 执行计划的最大部分是JobSteps的连接。

优先级是插入性能。数据出现在查询中可以容忍一些延迟(大约5分钟左右),因此复制到其他服务器并运行查询肯定是允许的。

除了将JobSteps加入Jobs之外,基于GUID的查找非常罕见。

当前设置:没有聚集索引。唯一一个似乎是候选者的是StartDate。但是,它并没有完美地增加。可以在StartDate后的3小时窗口中将作业插入任何位置。这可能意味着以非最终的顺序插入了一百万行。

1个Job + 1 JobStepId的数据大小,带有我当前的索引,大约是500个字节。

问题

  • 这是一个很好用的堆吗?

  • 群集在StartDate上有什么影响,当它几乎是非连续的~2小时/ 100万行?我的猜测是不断的重新排序会杀死插入性穿孔。

  • 我是否应该添加bigint PK只是为了拥有更小的,总是增加的密钥? (我仍然需要guid进行查找。)

我读过GUIDs as PRIMARY KEYs and/or the clustering key,似乎暗示即使发明密钥也会在其他索引上节省大量空间。另外一些资源表明堆通常存在某种性能问题,但我不确定它是否仍适用于SQL 2008.

再次,是的,我将尝试进行测试和测量。我只是想获得一些指导或链接到其他文章,这样我就可以考虑哪些路径做出更明智的决定。

4 个答案:

答案 0 :(得分:5)

是的,堆有问题。您的数据将在整个节目中按逻辑分段,并且不能简单地进行碎片整理。

想象一下,把你所有的电话簿扔进一个桶里然后试图找到“bob smith”。或者在lastname,firstname。上使用带有聚簇索引的传统电话簿。

维护索引的开销很小。

StartDate,除非是唯一的,否则不是一个好选择。聚簇索引需要非聚集索引的内部唯一性。如果没有声明唯一,SQL Server将添加一个4字节的“uniquifier”。

是的,我会使用int或bigint来简化它。至于GUID:请参阅屏幕右侧的问题。

编辑:

注意,PK和聚簇索引是2个独立的问题,即使SQL Server是默认的也会使PK聚集。

答案 1 :(得分:3)

堆碎片不一定是世界末日。听起来你很少会扫描数据,所以这不是世界末日。

您的非群集索引会影响您的效果。每个人都需要在underlynig表中存储行的地址(堆或聚簇索引)。理想情况下,您的查询永远不必使用基础表本身,因为它以理想的方式存储所需的所有信息(包括所有列,因此它是覆盖索引)。

是的,Kimberly Tripp的东西是最好的索引。

罗布

答案 2 :(得分:2)

正如您自己的研究所显示的那样,并且正如所有其他回答者所提到的那样,使用GUID作为表上的聚集索引是一个坏主意。

但是,拥有堆也不是一个好的选择,因为堆有其他问题,主要是与碎片和其他与堆不兼容的事情有关。

我的最佳实践建议始终如下:

  • 在任何数据表上使用主群集密钥(除非它是临时表或用于批量加载的表)
  • 尝试确保群集密钥是INT IDENTITY或BIGINT IDENTITY

我认为通过添加INT / BIGINT获得的好处 - 即使只是为了拥有良好的聚集索引 - 远远超过了它的缺点(正如Kim Tripp在她引用的博客文章中所说的那样)。

马克

答案 3 :(得分:1)

由于GUId是您的主键和外键,您的数据库仍然需要检查每个插入的约束,您可能需要将其编入索引。由于它的随机性,不建议为GUId编制索引。因此,我绝对会说你应该将你的主键的bigint(可能是身份)路由下去并将其用作聚簇索引。