我爱我的 GUID。然而,最近我一直在做一些研究来了解主键的 IDENTITY 的实际优点/缺点,我发现这篇文章很好地总结了它。
作者在文章中写道:
- 对数据仓库非常有用;
作为使用 IDENTITY over GUID 的优点之一。
我会理解,对于特别大的数据库,就像数据仓库一样,大小确实很重要——但似乎还有其他原因,本文未能解释。所以我问:
为什么 GUID 对日期仓储来说不是一个好主意?
我爱我的 GUID。然而,最近我一直在做一些研究来了解主键的 IDENTITY 的实际优点/缺点,我发现这篇文章很好地总结了它。
作者在文章中写道:
- 对数据仓库非常有用;
作为使用 IDENTITY over GUID 的优点之一。
我会理解,对于特别大的数据库,就像数据仓库一样,大小确实很重要——但似乎还有其他原因,本文未能解释。所以我问:
为什么 GUID 对日期仓储来说不是一个好主意?
GUID 似乎是您的主键的自然选择 - 如果您真的必须,您可能会争辩将它用于表的 PRIMARY KEY。我强烈建议不要使用 GUID 列作为clustering key,SQL Server 默认会这样做,除非您明确告诉它不要这样做。
您确实需要将两个问题分开:
1)主键是一个逻辑构造 - 唯一且可靠地标识表中每一行的候选键之一。这可以是任何东西,真的 - 一个 INT、一个 GUID、一个字符串 - 选择对您的场景最有意义的东西。
2)聚集键(在表上定义“聚集索引”的一列或多列)——这是一个与物理存储相关的东西,在这里,一个小的、稳定的、不断增长的数据类型是你最好的选择——INT或 BIGINT 作为您的默认选项。
默认情况下,SQL Server 表上的主键也用作集群键——但不必这样!在将以前的基于 GUID 的主键/集群键分解为两个单独的键——GUID 上的主(逻辑)键和单独INT IDENTITY(1,1)
列上的集群(排序)键时,我个人看到了巨大的性能提升。
正如金伯利·特里普( Kimberly Tripp)——索引女王——和其他人多次声明的那样——GUID
因为集群键不是最优的,因为由于它的随机性,它会导致大量的页面和索引碎片,并且通常会导致性能不佳。
是的,我知道 -newsequentialid()
在 SQL Server 2005 及更高版本中存在 - 但即使这样也不是真正的和完全顺序的,因此也会遇到与 - 一样的问题GUID
- 只是稍微不那么突出。
然后还有另一个问题需要考虑:表上的集群键也将添加到表上每个非聚集索引的每个条目中 - 因此您真的希望确保它尽可能小。通常,具有 2 亿以上行的 INT 对于绝大多数表来说应该足够了 - 与作为集群键的 GUID 相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。
快速计算 - 使用 INT 与 GUID 作为主键和聚类键:
总计:25 MB 与 106 MB - 这只是在一张桌子上!
更多值得深思的东西——金伯利·特里普(Kimberly Tripp)的优秀作品——读一读,再读一遍,消化一下!这是 SQL Server 索引的福音,真的。
马克
IDENTITY 字段创建小而漂亮的索引。它们也是 SEQUENTIAL,这意味着为它们创建的索引比常规 GUID 键索引的碎片更少。使用 SEQUENTIAL GUID 将使您更接近这种行为,但它仍然有其缺点。GUID 的一个优点是即使在数据库中它也往往是唯一的,但它在大多数应用程序中会影响性能和空间。
GUID 优点 在每个表、每个数据库、每个服务器中都是唯一的 允许轻松合并来自不同数据库的记录 允许在多个服务器之间轻松分发数据库 您可以在任何地方生成 ID,而不必往返于数据库 大多数复制方案无论如何都需要 GUID 列
GUID 缺点 它比传统的 4 字节索引值大 4 倍;如果您不小心,这可能会对性能和存储产生严重影响 调试繁琐(其中 userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}') 生成的 GUID 应该部分顺序以获得最佳性能(例如,newsequentialid() on SQL 2005) 并启用聚集索引
另外,要专门回答您的问题:我不认为您所引用的文章说“GUID 对于数据仓库来说是个坏主意”,而是说“身份”字段在数据仓库中比自然键更有用。但是,如果您在数据仓库中存储大量记录,由于上面的索引投诉,您将通过使用 IDENTITY 列而不是 GUID 获得更好的性能和更小的存储需求,我会说这是主要缺点。
使用 4 字节整数的主要原因是您尝试将行大小保持在最小。鉴于一个事实表可以包含 1 亿行,每行节省 12 个字节是一个可观的节省。
当然,这假设您的行数少于 2^31 - 1...
此外,插入标识列(使用默认聚集索引)不会导致页面拆分,而使用 GUID 列上的聚集索引插入会导致页面拆分。
虽然严格来说代理/事实 ID 键应该是匿名且无意义的,但我发现,对于非常大的事实,报告基于大范围的日期,使日期的代理键成为表示日期的整数(例如 20120830)允许您可以在不实际加入日历维度的情况下运行查询。您将无法使用 GUID 执行此(有问题的)技巧。我还发现在维度中拥有一组未知成员很有用,例如在日历维度中,0 的代理表示“日期尚不可用”,-1 表示“未知”,-2 可能表示“迟到的日期” -即晚于日历范围内的最大日期。-3 可能表示“早期日期”等。使用 GUID 可能会出现问题。
读了你的问题后,我有了一些想法
GUID 主要用于 MS 世界.. 在我 12 多年的 DWH exp 中没有见过 GUID ......
Identity 列很可能会成为表的代理键,让它们自动递增会更有意义...我不确定 GUID 是否可以为我们提供这种功能...
索引数字列比索引字母数字列要快得多。基于数字列的索引更小,访问速度更快……
hth
因为在标识上的索引比在 GUID 上的效率更高。