我应该为我的sqlalchemy模型使用代理键(id = 1)还是自然主键(tag ='sqlalchemy')?

时间:2011-06-21 11:29:49

标签: python sql orm sqlalchemy primary-key

在数据库方面,我认为自然主键是可取的,只要它不会过长,这会导致索引性能问题。但是当我正在阅读通过谷歌代码搜索使用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吗?

3 个答案:

答案 0 :(得分:3)

虽然ORM或编程语言比其他语言更容易使用,但我认为选择主键是与ORM无关的数据库设计问题。以自己的理由获得数据库架构更为重要。无论如何,数据库的寿命往往比访问它们的代码更长。

搜索SO(和谷歌)以获取有关如何选择主键的更多一般性问题,例如:https://stackoverflow.com/search?q=primary+key+natural+surrogate+database-designSurrogate vs. natural/business keysRelational 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关于这个主题的博客文章,特别是第二篇和第三篇文章:

我强烈建议人们阅读这些文章,因为这些文章来自一位花了数十年时间作为数据库专家的人。

如今代理密钥的使用让我想起了21世纪的早期,当时人们使用XML来实现所有内容,包括它所属的地方以及不属于它的地方。