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