当我创建新的数据库表时,我应该考虑哪些因素来选择主键的数据类型?
答案 0 :(得分:11)
很抱歉这样做,但我发现我给相关问题的答案(您可以查看this和this)可能适用于此问题。我重塑了一下......
你会发现许多关于这个问题的帖子,你所做的每一个选择都有其优缺点。这些参数通常是指关系数据库理论和数据库性能。
关于这个问题,我的观点很简单: 代理主键始终有效 ,而 自然键可能不会总是工作这些天 ,这有多种原因:字段太短,规则发生变化等等。
到目前为止,你已经猜到我基本上是uniqueIdentifier / surrogate主键团队的成员,即使我欣赏和理解这里提出的论点,我仍然在寻找这样的情况: “自然”关键比代理更好......
除此之外,支持此基本规则的最重要但始终被遗忘的论据之一与代码规范化和生产力有关:
每次创建表格时,我都会浪费时间
我对所有这些问题的答案都不是:
所以我在过去的五年里一直在用一个非常基本的规则工作:每个表(我们称之为'myTable')有第一个名为'id_MyTable'
的字段,它是uniqueIdentifier类型。即使此表支持“多对多”关系,其中字段组合提供了非常可接受的主键,我更喜欢将此'id_myManyToManyTable'
字段创建为uniqueIdentifier,只是为了坚持该规则,并且因为最后,它没有受伤。
主要优点是您不必再关心代码中主键和/或外键的使用。获得表名后,就会知道PK名称和类型。一旦知道数据模型中实现了哪些链接,就会知道表中可用外键的名称。
如果您仍想在表格中的某个位置放置“自然键”,我建议您按照标准模型(例如
)构建它Tbl_whatever
id_whatever, unique identifier, primary key
code_whatever, whateverTypeYouWant(whateverLengthYouEstimateTheRightOne), indexed
.....
其中id_是主键的前缀,code_用于“自然”索引字段。有些人认为code_字段应该设置为唯一。这是事实,可以通过DDL或外部代码轻松管理。请注意,计算了许多“自然”键(发票号),因此它们已经通过代码
生成我不确定我的规则是最好的。但这是一个非常有效的!如果每个人都在应用它,我们会避免时间丢失回答这类问题!
答案 1 :(得分:7)
如果使用数字键,请确保数据类型为giong,以便保留表格可能会增长到的行数。
如果使用guid,是否需要考虑存储guid所需的额外空间?针对guid PK的编码对于应用程序的开发人员或用户来说是一种痛苦。
如果使用复合键,您确定组合列始终是唯一的吗?
答案 2 :(得分:7)
我真的不喜欢他们在学校教的东西,即使用“自然键”(例如书籍数据库中的ISBN),或者甚至使用2个或更多字段构成的主键。我永远不会那样做。所以这是我的小建议:
编辑:
好的,我想我需要解释一下我的选择。
在所有表中为您的主键设置专用列名称,只是使您的SQL语句更容易构建,更容易为其他人(可能不熟悉您的数据库布局)更容易了解。特别是当你做很多JOINS和类似的事情时。您已经知道,您不需要查找特定表的主键是什么,因为它在任何地方都是相同的。
GUIDs与INTs在大多数情况下并不重要。除非您达到GUID的性能上限或进行数据库合并,否则您不会遇到任何重大问题。 但是这是我更喜欢GUID的原因。 GUID的全球唯一性有朝一日可能会派上用场。也许你现在看不到它的需要,但是诸如将数据库的各个部分同步到笔记本电脑/手机甚至找不到数据线而不需要知道它们在哪个表中,这些都是GUID优点的优秀例子。提供。整数仅标识一个表的上下文中的记录,而GUID标识任何地方的记录。
答案 3 :(得分:6)
在大多数情况下,我使用identity int主键,除非场景需要大量复制,在这种情况下我可以选择GUID。
我(几乎)从未使用过有意义的密钥。
答案 4 :(得分:4)
除非您有一个非常方便的自然键,否则请始终使用数字类型的合成(a.k.a.代理)键。即使您确实有可用的自然键,您也可以考虑使用合成键并在自然键上添加其他唯一索引。考虑当联邦法律改变时,使用社会安全号码作为PK的高等数据库发生了什么,转换到合成密钥的成本是巨大的。
另外,我不同意将每个主键命名为相同的做法,例如: “ID”。这使查询更难理解,而不是更容易。主键应以表格命名。例如employee.employee_id,affiliate.affiliate_id,user.user_id等。
答案 5 :(得分:2)
不要使用浮点数字类型,因为无法正确比较浮点数。
答案 6 :(得分:1)
到目前为止,我已使用uniqueidentifiers(GUID)或递增整数。
干杯 的Matthias
答案 7 :(得分:1)
在现实世界中具有意义的数字通常是一个坏主意,因为现实世界经常会改变关于如何使用这些数字的规则,特别是允许重复,然后你真的搞得一团糟你的手。
答案 8 :(得分:0)
我通常总是使用整数,但这是一个有趣的观点。
https://blog.codinghorror.com/primary-keys-ids-versus-guids/
答案 9 :(得分:0)
我偏向于使用生成的整数键。如果您希望数据库变得非常大,可以使用bigint。
有些人喜欢使用guids。专业人员可以合并数据库的多个实例,而无需更改任何键,但可以看出性能会受到影响。
答案 10 :(得分:0)
对于“自然”键,无论哪种数据类型都适合列)。人工(代理)键通常是整数。
答案 11 :(得分:0)
一切都取决于。
a)您是否可以使用唯一的连续数字作为主键?如果是,则选择UniqueIdentifier作为主键就足够了。 b)如果您的业务需求需要使用字母数字主键,那么您必须使用varchar或nvarchar。
这是我能想到的两个选项。
答案 12 :(得分:0)
一个很重要的因素是您要存储多少数据。我在网络分析公司工作,我们有数据负载。因此,由于大小,我们的网页浏览表上的GUID主键会杀死我们。
经验法则:为了获得高性能,您应该能够将整个索引存储在内存中。 Guids很容易打破这个!
答案 13 :(得分:0)
在可信任时使用自然键。一些自然键的来源不可信任。多年前,社会保障管理局曾经偶尔搞砸了为两个不同的人分配相同的SSN。他们现在可能已经解决了这个问题。
您可以信任车辆的VIN和书籍的ISBN(但不能信任可能没有ISBN的小册子)。
如果使用自然键,则自然键将确定数据类型。
如果您不相信任何自然键,请创建一个合成键。为此,我更喜欢整数。留出足够的空间进行合理的扩展。
答案 14 :(得分:0)
我通常使用所有表的GUID列主键(mssql中的rowguid)。什么可能是我做出独特限制的自然键。一个典型的例子是用户必须弥补的产品标识号,并确保它是唯一的。如果我需要一个序列,就像在发票中我构建一个表来保留lastnumber和存储过程以确保序列化访问。或Oracle中的一个序列:-)我讨厌自然键的“社会安全号码”样本,因为在注册过程中该号码永远不会被捕获。导致需要一个生成虚拟数字的方案。
答案 15 :(得分:-1)
尽可能尝试使用自然键的主键。例如,如果我有一个表每天记录一条记录,那么logdate将是一个很好的主键。否则,如果没有自然键,只需使用int。如果您认为将使用超过20亿行,请使用bigint。有些人喜欢使用GUID,它们很有效,因为它们是独一无二的,你永远不会用完空间。但是,它们不必要很长,如果您只是在进行特殊查询,则很难输入。