什么原因*不*使用GUID作为主键?

Yar*_*rin 23 sql database-design relational-database

每当我设计一个数据库时,我都会自动为每个表启动一个自动生成的GUID主键(除了查找表)

我知道我永远不会因重复键,合并表等而失眠.对我来说,哲学上任何特定记录在所有域中都应该是唯一的,并且这种唯一性应该从表到表以一致的方式表示.

我意识到它永远不会是最高效的选择,但是把表现放在一边,我想知道是否有反对这种做法的哲学论据?

根据回复,让我澄清一下:

我所说的一直使用GUID代理键作为主键 - 无论是否以及如何在表上设计任何自然键或顺序键.这些是我的假设:

  1. 基于自然键的数据完整性可以设计用于但不是假设的.
  2. 主键的功能是参照完整性,与性能,排序或数据无关.

mar*_*c_s 16

GUID似乎是您主键的自然选择 - 如果您真的必须,您可能会争辩将其用于表的PRIMARY KEY.

我强烈建议不要使用GUID列作为群集密钥,默认情况下SQL Server会执行此操作,除非您明确告知不要这样做.这样做的主要原因确实是性能,它会让你感到困惑......(它会信任我 - 只是时间问题) - 还浪费资源(SQL Server中的磁盘空间和RAM)机器)这是真的没有必要.

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

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作为主要和群集密钥:

  • 基表有1'000'000行(3.8 MB对15.26 MB)
  • 6个非聚簇索引(22.89 MB对91.55 MB)

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

还有一些值得思考的东西 - 金伯利·特里普的优秀作品 - 阅读,再读一遍,消化它!这是SQL Server索引福音,真的.


Eva*_*gle 14

Jeff Atwood详细讨论了这个问题:http:
//www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html

Guid优点:
每个表,每个数据库,每个服务器都是唯一的
允许轻松合并来自不同数据库的记录
允许跨多个服务器轻松分发数据库
您可以在任何地方生成ID,而不必往返数据库
大多数复制方案都需要GUID列

Guid Cons:
它比传统的4字节索引值大4倍; 如果你不小心
调试麻烦(其中userid ='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
,这会产生严重的性能和存储影响.生成的GUID应该是部分顺序的以获得最佳性能(例如,newsequentialid()on SQL 2005)并支持使用聚簇索引

  • 如果您不进行复制,那么我从未见过使用 GUID 来合并记录,因为通常最重要的是内容。此外,由于外键,我很少合并,我希望能够定期进行。如果我的数据库是分布式的或将被复制,我会添加它们,否则我依赖日期时间戳。 (2认同)