Database 如何在UUID、自动增量/序列键和数据库主键的序列表之间进行选择?

Database 如何在UUID、自动增量/序列键和数据库主键的序列表之间进行选择?,database,database-design,sequence,uuid,auto-increment,Database,Database Design,Sequence,Uuid,Auto Increment,我将介绍这三种为数据库行生成主键的主要方法的优缺点 所以假设我使用的数据库支持这些方法中的不止一种,有没有一个简单的启发式方法来确定我的最佳选择 如何考虑分布式/多主机、性能要求、ORM使用、安全性和测试等因素 可能遇到的任何意外缺陷?UUIDs 除非这些是“按递增单调序列”生成的,否则它们可能会极大地破坏/分割索引。对UUID生成的支持因系统而异。虽然可用,但在大多数情况下,我不会将UUID用作我的主聚集索引/PK。如果需要的话,我可能会把它作为第二列,也许是索引的,也许不是 有些人认为UUI

我将介绍这三种为数据库行生成主键的主要方法的优缺点

所以假设我使用的数据库支持这些方法中的不止一种,有没有一个简单的启发式方法来确定我的最佳选择

如何考虑分布式/多主机、性能要求、ORM使用、安全性和测试等因素

可能遇到的任何意外缺陷?

UUIDs

除非这些是“按递增单调序列”生成的,否则它们可能会极大地破坏/分割索引。对UUID生成的支持因系统而异。虽然可用,但在大多数情况下,我不会将UUID用作我的主聚集索引/PK。如果需要的话,我可能会把它作为第二列,也许是索引的,也许不是

有些人认为UUID可以用于从任意数量的系统安全地生成/合并记录。虽然UUID(取决于方法)发生碰撞的几率通常非常小,但至少在一些外部输入或非常糟糕的情况下,它有可能生成碰撞。我相信只有真正的PK应该在系统之间传输,我认为在大多数情况下,PK不是(或不应该是)数据库生成的UUID

自动递增/顺序键和顺序表

这实际上取决于数据库支持什么。有些数据库支持比简单的“自动增量”更灵活的序列。这可能是可取的,也可能不是可取的(甚至可能是完成这类任务的唯一方法)。序列表通常更灵活,但是如果需要这种“灵活性”,我会尝试返回并访问设计模式,特别是当它涉及到触发器的使用时。虽然我不喜欢“限制ORM”,但选择“更简单”的自动增量或序列类型/数据库支持也可能会有所不同

无论使用哪种方法,当使用代理主键时,真正的主键仍然应该被识别并编码到模式中

此外,我认为“通过公开自动序列PK导致的安全性损害”是错误地公开内部数据库属性的结果。虽然这是处理CRUD操作的一种非常简单的方法,但我相信内部密钥和公开密钥(例如,漂亮的客户号)之间有区别

只要我的两分钱

编辑,对Tim的其他回复:


我认为生成的vs.真的PK问题是一个非常好的问题,也是我需要考虑的问题。我希望UUID大体上与您的观点一致。我犹豫不决的是大小对整数/长。没有意识到潜在的索引去优化,这对我来说是一个更大的问题

我不会真的担心大小——如果UUID是最好的,那么它就是最好的。如果不是,那就不是。在整个方案中,int上额外的12字节可能不会有多大区别。SQL Server 2005+支持UUID生成功能,以避免与正常UUID生成相关的碎片。本页对此进行了一些讨论。我相信其他数据库也有类似的解决方案

“编码到模式中”,您的意思是否不仅仅是添加唯一性约束

对。主键不必是唯一的[唯一]约束。仅仅使用代理PK并不意味着数据库模型应该受到损害:-)还可以使用其他索引来覆盖,等等

通过“区分”,你是说代理主键永远不会泄漏吗

我第一篇文章的措辞有点难。与其说是“从未”,不如说是“如果他们这样做了,这很重要,那就是另一个问题”。通常,人们会通过猜测的数字抱怨不安全——例如,如果您的订单是23,则可能有订单22和24,等等。如果这是您的“保护”和/或可能泄漏敏感信息,则系统已存在缺陷。(分离内部和外部ID并不能从本质上解决这个问题,仍然需要身份验证/授权。但是,这是使用“顺序ID”时遇到的一个问题——我发现将nonce编码到分布式URL对于我的用例来说可以很好地处理这一问题。)

我真正想表达的是:仅仅因为代理PK id恰好是8942并不意味着它是8942订单。也就是说,按照“某些字段仅在db内部”的设计,订单“编号”表面上可能完全不相关(但在db模型中完全受支持),例如“#2010-42c”或任何对业务需求有意义的内容。在大多数情况下,应该公开的就是这个外部数字

我觉得有时候生成的密钥实际上是真正的主键,因为其他字段是可变的(例如,用户可能会更改电子邮件和用户名)

在数据库中可能就是这种情况,我不会对这种说法进行争辩。但是,再次认为代理PK是数据库内部的,只需确保只导出/导入可以很好识别的元组。如果用户名/电子邮件可能会更改,那么这很可能包括在创建帐户时分配的UUID——很可能是代理PK本身

当然,与一切一样,保持开放,使模型适应问题,而不是模型的问题:-)例如,对于twitter这样的服务,他们使用自己的数字生成模式。看见与[某些]UUID生成不同,twitter的方法(假设所有服务器都正确设置)保证所有分布式机器/进程都不会生成重复的ID,只需要64位,并保持粗略排序(最重要的位是时间戳)。(twitter生成的记录数量可能不会太多