我知道我永远不会因为重复的键、合并表格等问题而失眠。在我看来,在所有领域中,任何给定的记录都应该是唯一的,并且这种独特性应该从表格到表格以一致的方式表示。
我意识到这永远不会是最有效的选择,但是把性能放到一边,我想知道是否存在反对这种做法的哲学论据?
根据回答让我澄清:
我所说的是始终使用GUID代理键作为主键-无论是否以及如何在表格上设计任何自然或顺序键。这些是我的假设:
基于自然键的数据完整性可以进行设计,但不能假定。
主键的功能是参照完整性,与性能、排序或数据无关。
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作为聚集键并不是最佳选择,因为由于其随机性,它会导致大量页面和索引碎片以及普遍的性能问题。是的,我知道 - 在SQL Server 2005及以上版本中有newsequentialid()
,但即使这样也不是真正的完全顺序,因此也会遇到与GUID相同但稍微不那么突出的问题。还有一个问题需要考虑:表上的聚集键也将添加到表上每个非聚集索引的每个条目中 - 因此您确实希望尽可能使其尽可能小。通常,具有20亿行的INT对于绝大多数表来说应该足够了 - 而与GUID作为聚集键相比,您可以节省数百兆字节的磁盘存储空间和服务器内存。
快速计算 - 使用INT vs. GUID作为主键和聚集键:
总计:25 MB vs. 106 MB - 这仅仅是单个表格!
还有更多值得思考的内容 - Kimberly Tripp的优秀文章 - 读一读,再读一遍,消化一下!这真的是SQL Server索引的福音。
Marc
Jeff Atwood在他的博客中详细讨论了这个问题:
http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html
Guid的优点:
在每个表、每个数据库和每个服务器中都是唯一的
允许轻松地合并来自不同数据库的记录
允许轻松地将数据库分布在多个服务器上
可以在任何地方生成 ID,而不必往返到数据库
大多数复制场景都需要 GUID 列
Guid的缺点:
它比传统的 4 字节索引值大 4 倍;如果不小心处理会对性能和存储造成严重影响
调试起来比较麻烦(例如:where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
为获得最佳性能(例如在 SQL 2005 上使用 newsequentialid())并启用聚集索引,生成的 GUID 应该是部分顺序的
补充说明:
优点
缺点
简单回答:它不是关系型的。
该记录(由GUID定义)可能是唯一的,但不能说其中任何一个相关的属性是唯一地发生在该记录中。
使用GUID(或任何纯代理键)与将平面文件声明为关系型没有区别,因为每个记录可以通过其行号进行标识。
我想知道为什么没有标准的“miniGUID”类型?在GUID上执行一个不错的哈希应该会产生一个64位数字,在任何宇宙中都有微不足道的重复概率,除非它有十亿个或更多的事物。由于大多数GUID/miniGUID标识符使用的宇宙永远不会超过一百万件事物,更不用说十亿了,因此我认为一个更小的8字节miniGuid将非常有用。
当然,这并不意味着它应该用作聚集索引;那样会严重影响性能。尽管如此,与4字节索引相比,8字节的miniGUID只会浪费三分之一的空间。
我可以理解为给定应用程序或企业自己的标识符在所有其自己的域中以一致的方式表示并保持唯一性(即因为它们可能跨越多个数据库),但是对于这些目的来说,GUID过于复杂了。我猜它们很受欢迎,因为它们可以直接使用,而设计和实现“企业键”需要时间和精力。设计人工标识符的规则是尽可能简单,但不要太简单。IDENTITY太简单了,GUID不够简单。
存在于应用程序/企业之外的实体通常具有自己的标识符(例如汽车具有VIN,书籍具有ISBN等),由外部可信源维护,在这种情况下,GUID没有任何作用。因此,我想表达的哲学论点是,在每个表上使用人工标识符是不必要的。