是否有理由对主键使用单个递增字段而不是实际表示唯一记录的多个字段?
我正在开发一个现有的php应用程序,这些表似乎只有一个“id”键,而不是使用实际上对记录唯一的2个或更多字段(如用户,拍卖,出价)。
我不是数据库专家,但这对我来说似乎很懒(或没有经验)。是否有任何好处(表现或其他方面)?
已更新:我不是指psudo唯一数据(ssn,电子邮件地址等),您可能希望确保数据真正唯一。我在谈论具有明显外键引用的表,但不是将这些引用与表本身中的唯一字段一起使用,而是每个表只有一个递增ID。
不试图启动主观辩论,这对我来说没有意义。
答案 0 :(得分:5)
这取决于“独特”的定义。是的,名称,电子邮件地址和SSN值应该是“唯一的”。但是,发生了一些奇怪的事情。在很多情况下,拥有单独的ID值可以让生活变得更轻松......
<强>更新强>
根据问题的编辑,我并没有真正看到需要。听起来你的情况就像。一个“连接表”,您只需创建一个表中的UniqueId与另一个表的UniqueId的关联。
我正在考虑的一个简单例子是用户 - &gt;角色关联。您必须将用户与角色相关联。 UserId和RoleId。
您的数据库中有一个类似于
的结构MappingId (Your Auto Number) (This is the PK)
UserId (From the user table)
RoleId (From the Role table)
这个结构对我没有意义,我只需要User和RoleId组成主键,因为这里不需要重复条目。
如果你有不同的东西可能会改变一些事情......
答案 1 :(得分:5)
使用合成主键有几个优点:
数据库通常具有围绕使用单调递增键构建索引的特定优化。
话虽如此,偶尔进行一些非规范化并没有错。如果用例很清楚且表格相对较小,那就方便了。
答案 2 :(得分:3)
最简单的原因是防止数据冗余。自然键往往需要多个密钥,这些密钥可能会在数据库的生命周期内发生变化。
例如,如果一个人结婚并更改了他们的姓氏,那么该姓氏必须在所引用的任何地方更新。
如果您将外键设置为更新级联,这不是问题,因为数据库会为您执行此操作。
随着您的表越来越深,您可能会发现您的密钥需要越来越多的列。我实际上看过一个有七列主键的表。对于只有四个其他列的表。
答案 3 :(得分:1)
您通常需要主键上的聚簇索引。使用复合群集主键的问题是,当您插入新行时,SQL必须将新记录粘贴在其他记录之间,这意味着改组。此外,主键越大,存储它所需的空间就越大。
Here是一篇关于使用GUID作为主键的文章,但对于复合键也是如此。
答案 4 :(得分:0)
好吧,id会从1-infinity对数据库进行顺序排序。用户名等是暂时的,并不总是有序。因此,据推测,它会使搜索速度更快。此外,您似乎建议让多个键表示一个项目。这通常会减慢速度,因为现在必须检查两件事以确保某些东西是正确的而不是一件。
答案 5 :(得分:0)
以下是使用自动编号的几点
自动编号是一个唯一的密钥 制造外键关系 更容易维护和使用
自动编号是数字,所以很容易使用它们而不是乱七八糟 他们了我的意思是,如果你的 主键是一个字符串和你的 开发人员忘了把它放进去 单引号会摧毁你的 性能
使用自动编号是正常的标准做法
您仍然可以将其他字段设为“唯一”
使用自动编号重新设置序列
如果你需要在序列中向前跳,那么使用它会更容易 数字比组合的属性,或 字符串
只是一些事情......
答案 6 :(得分:0)
在大多数情况下,当这些字段真正唯一地标识记录所代表的实体时,它实际上并不明确。我一次又一次地看到了商业心态中存在的旧数据库概念妨碍任何进一步发展的情况。
答案 7 :(得分:0)
是的,这会刺激辩论。
通常,主键数据应该是不可变的,当使用从表数据派生的自然键时,通常不是这种情况。如前所述,像SSN这样的东西经常可以改变,从而摒弃了不变性。
单调增加代理键,如“autonumber”或“identity”列,是自然键的简单替代。但是,它们可能容易导致索引效率低下,因为它们可能无法在B树样式索引算法之间很好地平衡。这可以通过使用随机生成的代理键来解决,例如MS SQL Server中的uniqueidentifier,即GUID,但我读过这也有性能分支。
通常,我使用从自动编号或身份等顺序功能生成的代理键,以便于表连接。
答案 8 :(得分:0)
我曾尝试在数据库中使用的几乎所有“自然”组合键随着时间的推移而变得非常独特。随着抽象变得漏洞,数据模型需要快速发展。
包括姓名,电话号码,SSN,法律文件参考,页码,电子邮件地址,用户名,项目编号以及我在职业生涯中尝试使用的其他一些内容。
除此之外,关于写新记录,比较外键等的表现的其他答案仅仅是足够的理由。
您可以保留当前的唯一性业务逻辑,而无需将其烘焙到主键中 - 只需在自然键列上设置唯一索引即可。与任何索引一样,您将为插入和更新付出代价,但如果它恰好也是有用的索引(有助于覆盖某些查询),那就更好了。
答案 9 :(得分:0)
这一切都归结为您的数据结构是如何“正常”的。根据定义,高度规范化的数据库只能具有主键的单个字段。在这种情况下,几乎没有理由使用串行或自动生成的数字作为PK。数据结构应设计为具有唯一条目作为PK(跟踪人是一个问题,只有这么多名称)。
当然,规范化带来了性能损失,因此数据库被非规范化以使其可用(对于Web应用程序非常常见)。对于严重去标准化的数据库,很多时候如果不使用表中的每个字段就不可能获得PK。请记住,结构被去规范化的原因是为了提高性能。我熟悉的所有数据库都为每个PK构建索引。索引越大,维护索引的开销就越大。
构建巨大的索引将终止插入并更新时间性能,使去规范化无效(除非它是只读数据库)。搜索巨大的索引并使用比较小的索引更多的内存也需要更长的时间。
总之,出于性能原因,为任何需要多个字段才能获得唯一PK的表自动生成PK通常是有利的。