在数据库方面,我认为自然主键是可取的,只要它不会过长,这会导致索引性能问题。但是当我正在阅读通过谷歌代码搜索使用sqlalchemy的项目时,我几乎总能找到类似的东西:
class MyClass(Base):
__tablename__ = 'myclass'
id = Column(Integer, primary_key=True)
如果我有一个简单的类,比如标签,我只计划存储一个值并且需要唯一性,当我使用sqlalchemy时,通过代理主键可以获得什么?我正在阅读的一本SQL书籍暗示ORM是“反模式”的合法用法,但他设想的ORM更像是ActiveRecord或Django。这出现在我的模型中的一些地方,但这里有一个:
class Tag(Base):
__tablename__ = 'tag'
id = Column(Integer, primary_key=True) #should I drop this and add primary_key to Tag.tag?
tag = Column(Unicode(25), unique=True)
....
在我更广泛的关系模型中,Tag与其他对象具有多个多对多关系。因此,将有许多中间表必须存储更长的密钥。我应该为我的主键选择标签或ID吗?
答案 0 :(得分:3)
虽然ORM或编程语言比其他语言更容易使用,但我认为选择主键是与ORM无关的数据库设计问题。以自己的理由获得数据库架构更为重要。无论如何,数据库的寿命往往比访问它们的代码更长。
搜索SO(和谷歌)以获取有关如何选择主键的更多一般性问题,例如:https://stackoverflow.com/search?q=primary+key+natural+surrogate+database-design(Surrogate vs. natural/business keys,Relational database design question - Surrogate-key or Natural-key?,When not to use surrogate primary keys?,...)
我认为Tag
表不会很大或非常动态。
在这种情况下, I 会尝试使用tag
作为主键,除非有重要原因要添加一些对最终用户主键不可见,例如:< / p>
现实世界数据下的表现不佳(测量,未想象),
频繁更改标签名称(但是,我仍然会根据首次使用的标签名称作为密钥使用一些唯一的字符串),
不可见的幕后合并标签(但是,请参阅上一点),
不同排序规则的问题 - 比较国际数据 - 在您的RDBMS中(但是......)
...
总的来说,我发现人们往往会在两个方向上犯错误:
通过使用复杂的多字段“自然”键(其中特定字段本身是不透明的数字),当表行具有自己的标识并且可以从拥有自己的代理ID中受益时,
为所有内容引入随机数字代码,而不是使用短有意义的字符串。
有意义的主键值 - 如果可能 - 在手动浏览数据库时证明自己很有用。您不需要多个连接来计算数据。
答案 1 :(得分:1)
就个人而言,我更喜欢大多数地方的代理钥匙;造成这种情况的两个最大原因是1)整数键通常更小/更快; 2)更新数据不需要级联。对于你正在做的事情,第二点是相当重要的一点;如果有多个表引用标记表,那么请记住,如果有人想要更新标记(例如,修复拼写/案例错误,或使用更多/更少特定的单词等),更新将需要同时在所有表格中完成。
我不是说你永远不应该使用自然键 - 如果我确定自然键永远不会改变,我会考虑一个自然键。要确定,否则维持就会变得很痛苦。
答案 2 :(得分:0)
每当我看到人们(使用代理键)时,我都记得Roy Hann关于这个主题的博客文章,特别是第二篇和第三篇文章:
http://community.actian.com/forum/blogs/rhann/127-surrogate-keys-part-2-boring-bit.html
http://community.actian.com/forum/blogs/rhann/128-surrogate-keys-part-3-surrogates-composites.html
我强烈建议人们阅读这些文章,因为这些文章来自一位花了数十年时间作为数据库专家的人。
如今代理密钥的使用让我想起了21世纪的早期,当时人们使用XML来实现所有内容,包括它所属的地方以及不属于它的地方。