SQL-使用ORM时,对于多对多关系不使用数据透视表有时有意义吗?

问题描述

对于以下假设的用例,我试图理解为什么可能需要使用数据透视表而不是替代解决方案(下文概述)。

假想用例

让我们说一部电影有很多演员,而一个演员可以属于一部以上的电影。

“标准”数据透视表解决方

如本lesson (using Elixir's Ecto library)所述,“标准”解决方案建议使用movies_actors数据透视表,并且moviesactors表均引用此{{1} }表。

替代解决方

相反,我们可以通过具有ID列表的概念来达到相同的结果吗?

  • movies_actors属于一个或多个actor,因为movies表包含一个actors字段(这是一个列表)
  • movie_ids通过使movie表包含一个actors字段(它是一个列表)而具有许多movies

问题

一种解决方案更好吗?为什么?

解决方法

您所引用的表通常被称为“连接”表或“关联”表。这是实现多对多关系的标准方法。

连接表具有一些关键优势。值得注意的是,当正确定义外键时,它可以保证数据完整性。

但这不是您的问题。在某些情况下,其他表示是否合适?我想说Postgres通过数组和JSON提供了强大的功能,这使它们对多对多关系可行。特别是,Postgres支持数组和JSON上的索引,从而克服了这种关系的一大障碍。

这样的列表什么时候合适?我认为Actors不适合。那是一个独立的实体,您想要有关演员的许多其他信息。

但是它可能适用于诸如用户生成的标签之类的东西,尤其是那些您不需要维护主列表(并且不必担心拼写错误)的标签。某些情况下,它可能适合使用备用名称(假设您不希望在各行之间使用不连续的名称)。

,

我认为您不应该使用存储引用的id数组的“替代解决方案”来建立多对多关系的模型。乍一看似乎比较简单,但稍后会伤害您。

您应该为这两种情况编写一个简单的测试用例,并创建具有实际数量的条目和关系的测试表(数据是人工的还是重复的都没有关系)。然后尝试在两个表之间编写联接。您会发现,使用“替代解决方案”,查询看起来要复杂得多(充其量,它将涉及诸如@>之类的奇怪运算符),并且性能也不佳(您只能获得嵌套循环联接)

有充分的理由将数据保留在first normal form中–它更适合于关系数据库处理数据的方式。

当然,这种“正常形式”的东西必须要花点时间:只要您在查询处理中不使用单个数组条目,使用数组存储数据就可以了。但是通过联接数组元素,您肯定会越过那条线。