【问题标题】:PostgreSQL inheritance in ActiveRecord?ActiveRecord中的PostgreSQL继承?
【发布时间】:2012-04-08 23:18:28
【问题描述】:

所以我们都知道 Rails 的 STI(单表继承)很棘手,因为它会导致数据模型混乱和数据库不理想。

然而 PostgreSQL 似乎非常漂亮地处理继承!

有没有办法在利用 Postgres 继承而不是痛苦的宽表和“类型”列的同时获得 rails 干净整洁的 STI API?

【问题讨论】:

  • “所以我们都知道 Rails 的 STI(单表继承)很糟糕,因为它会导致数据模型混乱和数据库不理想。” --- 我不接受这个前提。
  • 好吧,也许这有点笼统。但是当您的子模型没有很多不适用于其他子模型的属性时,这往往是一个好主意。否则你结束加上充满可空列的超宽表。从 Rails 的角度来看可能没问题,但在数据库上运行原始 SQL 时可能会有点难看,也许 PostgreSQL 的继承并没有更快,但至少它对我隐藏了所有这些! :P
  • 因为 Postgres 的继承非常无缝,我不认为只有一个 type 列就足够了?从我所看到的继承来看,SELECT * 将返回所有关联的列(我猜所有未关联的列也是:/...但是您的数据库结构会更干净。

标签: ruby-on-rails postgresql inheritance activerecord


【解决方案1】:

然而 PostgreSQL 似乎非常漂亮地处理继承!

真的吗?你仔细看small print in the manual了吗?例如:

  • 唯一约束(因此也是主键)不可能超过继承级别。
  • 对继承表和基表的引用不能混合。 IE。 (大致摘自手册):capitals 扩展 cities。您的address 表想要引用cities。它可以。但是可以使用带有capital 的无地址。

这两件事在任何超出小型“Hello World”项目的情况下非常很重要。所以我无法想象,任何富有成效的事情都可以使用 PostgreSQL 继承来实现。

【讨论】:

  • 实际上据我了解,它对表分片非常有用。但它确实不适合现在的模型空间继承。
  • 在大多数情况下,即使是表分片也不可能:如果你有多个唯一约束,你就完蛋了。而且由于大多数框架都使用代理键,这意味着您甚至不能为应用程序数据设置一个唯一约束。
  • 当然,如果您使用代理键,那么分片通常会变得更加困难。 Psql 文档有一个很好的分片示例:postgresql.org/docs/9.1/static/ddl-partitioning.html
  • @Divide:我想,我重复原来的答案 ;-) 你仔细看看那个页面底部的小字了吗?对我来说,这看起来并不“好”,但相当丑陋,容易出错且维护密集。在大多数(如果不是全部)企业应用程序中,我开发的表分片 ala PostgreSQL 将是不可行的。
【解决方案2】:

简而言之 - 不,对于您现在要完成的工作,没有漂亮干净的 STI API。

实际上,大约一年前,我对此进行了研究,并得出结论认为这不是一个好主意,原因如下:

  1. 如果您想利用 PostgreSQL 的特定功能 - 您基本上就是将自己嫁给了那个数据库。不要误会我的意思,PostgreSQL 是一个很棒的数据库,我在很多场合都使用过它,但是你会被那个数据库和应用程序设计所困。
  2. 最有可能的是,如果您开始使用 DB 特定功能,您最终要么手动实现它们(在 DB 上运行某种命令或使用 GUI),要么编写某种脚本,您必须在运行时调用它们db:migrate (如果你想进行适当的测试,你必须这样做)。一段时间后,它会变得很麻烦和烦人。
  3. 如果您发现自己越来越讨厌,引用您“痛苦的宽表格和“类型”列”,那么:
    • 您的餐桌设计需要重新考虑和重做
    • 您的模型可能不适合 STI
    • 你只需要忍受它。

大多数 IT 问题都归结为:努力与收益。

在你的情况下,你应该问自己这个问题:

  • 您希望在实施更好的 STI 上花费多少时间 如果它只会将您的原始 SQL 查询加快几秒钟?也许写一个更明确的 SQL 查询会更好?大多数应用程序不会增长到真正成为问题的大小。但在您的情况下可能会有所不同。

附注:

还有一个关于在您的应用程序中构建 STI 的快速提示:如果您发现您有很多使用 STI 的模型,例如 ProductCategory、CommentCategory、PhoneCategory、ClientCategory,它们都继承自 Cateogory - 我倾向于将它们组织在里面的文件夹中模型目录。然后在 application.rb 中添加一行:config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**/**}')]

【讨论】:

  • 您在职业生涯中曾在什么时候切换过生产数据库引擎? :P 我说的是大公司,而不是你和你的 HS 朋友一起开始的“初创公司”,你是 CEO,她是 CTO。
  • 有点真实,也有点不真实。是的,除非您必须这样做,否则通常您不会过多地切换生产实现。 Twitter 和 Facbook 是浮现在脑海中的主要例子。您在一段时间内迁移到新设置。从你的个人经验来看 - 它发生在我身上好几次了。我不得不从旧的过时设置迁移内部应用程序。
  • @bwicklund - 好吧,问题是关于 ActiveRecord(Rails)中的 PostgreSQL 和 STI 以及是否有一种 NICE CLEAN 方法来处理它 - 答案是没有很好的干净方法来处理 STI,除了在简单的情况下,我解释了原因。只是因为你不喜欢这个答案并不意味着它错了。如果您有更好的解释,请随时提供您自己的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多