Skip to main content
 首页 » 编程设计

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

2025年05月04日18java哥

在数据库方面,我认为自然主键是更可取的,只要它不会太长,否则会导致索引性能问题。但是当我通过谷歌代码搜索阅读使用 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 与其他对象具有多个多对多关系。所以会有许多中间表必须存储更长的 key 。我应该为我的主键选择 tag 还是 id?

请您参考如下方法:

虽然 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 表不会非常大或非常动态。 在这种情况下,我会尝试使用 tag 作为主键,除非有重要的原因添加一些对最终用户不可见的主键,例如:

  • 现实世界数据(测量的,不是想象的)下表现不佳,

  • 标签名称的频繁更改(但是,我仍然会使用一些基于首次使用的标签名称的唯一字符串作为键),

  • 不可见的幕后标签合并(但是,请参阅上一点),

  • 在您的 RDBMS 中存在不同排序规则的问题——比较国际数据(但是,...)

  • ...


总的来说,我观察到人们倾向于在两个方向上犯错误:

  • 通过使用复杂的多字段“自然”键(其中特定字段本身是不透明数字),当表行具有自己的身份并且可以从拥有自己的代理 ID 中获益时,

  • 通过为所有内容引入随机数字代码,而不是使用有意义的短字符串。

如果可能的话,有意义的主键值将在手动浏览数据库时证明它们是有用的。您不需要多个连接来计算您的数据。