我正在设计一个供Web应用程序使用的小型SQL数据库。
假设一个特定的表有一个Name字段,其中不允许两行具有相同的值。但是,用户可以随时更改“名称”字段。
此表中的主键将用作其他表中的外键。因此,如果将Name字段用作主键,则需要将任何更改传播到其他表。另一方面,唯一性要求将自动处理。
我的直觉是添加一个整数字段作为主键,可以由数据库自动填充。有这个领域有什么意义,还是浪费时间?
答案 0 :(得分:25)
我会自己使用生成的PK,只是出于你提到的原因。此外,通过整数进行索引和比较比通过字符串进行比较更快。您也可以在名称字段上添加唯一索引,而不必将其作为主键。
答案 1 :(得分:11)
您所描述的内容称为代理键。有关详细答案,请参阅Wikipedia article。
答案 2 :(得分:6)
虽然搜索和加入整数列的速度更快(正如许多人所指出的那样),但是从来没有加入到第一位的速度更快。通过存储natural key,您通常可以消除对连接的需求。
对于一个小型数据库,CASCADE对外键引用的更新不会对性能产生太大影响,除非它们经常发生变化。
话虽如此,在这种情况下,您应该使用整数或GUID作为surrogate key。设计可更新的主键并不是最好的主意,除非您的应用程序具有非常引人注目的商业理由,否则您将不可避免地存在冲突。
答案 3 :(得分:2)
是的 - 根据经验,总是,每张桌子都有。
您绝对不应该使用可更改字段作为主键,并且在绝大多数情况下您不希望将具有任何其他用途的字段用作主键。
这是db模式的基本良好实践。
答案 4 :(得分:2)
从性能预期来看,使用整数主键始终是一件好事。使用整数主键,您的所有关系都将更加高效。例如,JOIN会更快(SQL Server)。
它还允许您将来修改数据库。通常,您只有一个唯一的名称列,以便稍后找出它根本不是唯一的名称。
现在,您可以通过在其上添加索引来强制列名称的唯一性。
答案 5 :(得分:2)
我会为主键使用自动生成的ID字段。基于整数ID而不是文本连接表更容易。此外,如果字段 Name 经常更新,如果它是主键,则数据库将更加频繁地更新该字段上的索引。
如果字段名称始终是唯一的,您仍应在数据库中将其标记为唯一。但是,通常会有两种相同名称的可能性(当前可能不会,但可能在将来可能),所以我不推荐它。
使用ID的另一个好处是,您的数据库需要报告。如果您有一组给定名称的报告,即使名称可能更改,报告上的ID过滤器也会保持一致。
答案 6 :(得分:1)
如果你生活在理论数学家的稀疏圈子里(比如C. Date就在那里 - 那里没有空,因为所有的数据值都是已知和正确的),那么主键可以从数据的组成部分构建,用于识别您所指的理想化柏拉图式实体(即名称+生日+出生地点+父母的名字),但在凌乱的现实世界中,“合成键”可以识别您的真实世界数据库上下文中的实体是一种更实用的方法。 (并且可空的字段可能非常有用。就这样,关系设计理论的人!)
答案 7 :(得分:1)
记录的主键必须是唯一的,永久。如果一个记录自然有一个简单的键来完成这两个,那么使用它。但是,它们并不经常出现。对于个人记录,该人的姓名既不是唯一的也不是永久性的,因此您几乎不得不使用自动增量。
自然键工作的一个地方是代码表,例如,将状态值映射到其描述的表。给“主动”主键1,“延迟”主键2等等几乎没有意义。当“主动”给主动键“ACT”同样容易; “延迟”,“DLY”; “暂停”,“HLD”等。
另请注意,有些人说你应该在字符串上使用整数,因为它们比较快。不是真的。比较两个4字节字符字段将花费与比较两个4字节整数字段完全相同的时间。更长的字符串当然需要更长的时间,但如果你保持代码简短,那就没有区别了。
答案 8 :(得分:1)
如果您的名称列将会更改,那么它实际上不是主键的理想选择。主键应定义表的唯一行。如果它可以改变它不是真的这样做。在不知道有关您的系统的更多细节的情况下,我不能说,但这可能是代理密钥的好时机。
我还要添加这个,希望消除为所有主键使用自动递增整数的神话。使用它们并不总是性能提升。事实上,通常情况恰恰相反。如果你有一个自动递增列,这意味着系统中的每个INSERT现在都有增加生成新值的开销。
另外,正如Mark所指出的那样,如果你有一个相关的表链,所有表上都有代理ID,要从一个表到另一个表,你可能必须将所有这些表连接在一起来遍历它们。使用自然主键通常不是这种情况。使用整数连接6个表通常比使用字符串连接2个表要慢。
当您在所有表上都有自动递增ID时,您通常也无法执行基于集合的操作。您不必在父表中插入1000行,然后在子表中插入5000行,而是必须在游标或其他循环中一次插入一行父行,以获取生成的ID,以便您可以分配它们给相关的孩子。我已经看到一个30秒的过程变成了一个20分钟的过程,因为有人坚持在数据库中的所有表上使用自动递增ID。
最后(至少由于我在这里列出的原因 - 肯定还有其他原因),在所有表格上使用自动递增ID会促使设计不佳。当设计人员不再需要考虑表格的自然键时,通常会导致数据中出现错误的重复。您可以尝试避免使用唯一索引的问题,但根据我的经验,开发人员和设计人员不会花费额外的努力,并且在使用他们的新系统一年后,他们发现数据很乱,因为数据库没有通过自然键对数据进行适当的约束。
肯定有时间使用代理键,但在所有表格上盲目使用它几乎总是一个错误。
答案 9 :(得分:0)
每一行的主键必须是唯一。 auto_increment Integer是个好主意,如果你没有关于填充主键的其他想法,那么这是最好的方法。
答案 10 :(得分:0)
除了所说的内容之外, 考虑使用UUID作为PK 。它将允许您创建跨越多个数据库的密钥。
如果您需要将数据导出/合并到其他数据库,那么数据将始终保持唯一,并且可以轻松维护关系。