1

我正在设计一个数据库表,它将保存用户最喜欢的食物列表。我使用以下架构创建了最喜欢的表

id, user_id, food_id

user_id 和 food_id 将是链接到另一个表的外键。

我只是想知道这是否有效且可扩展,因为如果用户有多个最喜欢的东西,那么它将需要多行数据。

即用户有 5 个最喜欢的食物,那么它将包含五行来保存该用户的列表。

这有效率吗?和可扩展?优化此架构的最佳方法是什么?

提前谢谢!!!

4

5 回答 5

6

tldr; 这称为“连接表” ,是在关系数据库中对 MM 关系建模的正确且可扩展的方法。(根据使用的约束,它还可以在“无 NULL FK”模式中建模 1-M/1-1 关系。)

但是,我认为此处应省略id列,以便该表仅为 user_id, food_id. PK将(user_id, food_id)在这种情况下。

与其他表不同,有时会争论代理(又称自动增量)PK,代理 PK 通常只会在连接表中增加混乱,因为它具有非常自然的复合 PK。

虽然在这种情况下 PK 本身是复合的,但每个“连接”表仅与 PK 的一部分相关联。根据执行的查询,在food_idor上添加覆盖索引也可能是有益的(food_id, user_id

于 2012-11-28T07:20:11.977 回答
2

消除代理键:除非您对代理键有特定原因id,否则将其从表中排除。

微调索引:此时,您只有一个复合主键,它是两个外键的组合。PK 字段应该按什么顺序排列?

  • 如果您的应用程序主要执行诸如“给定用户,给我食物”之类的查询,那么 PK 应该是{user_id, food_id}.
  • 如果主要查询是“给定食物,给我用户”,那么 PK 应该是{food_id, user_id}.
  • 如果两个查询“方向”都是通用的,则添加一个与 PK 具有相同字段但方向相反的 UNIQUE INDEX。因此,您将在 PK 上打开{user_id, food_id}索引并在{food_id, user_id}.

请注意,InnoDB 表是 clustered,这消除了(在这种情况下是“不必要的”)表堆。然而,上面讨论的二级索引不会导致双重查找(因为它完全覆盖了查询),也不会隐藏 PK 字段的开销(因为它索引与 PK相同的字段,只是顺序相反)。

有关设计接线表的更多信息,请查看这篇文章

于 2012-11-28T12:09:29.033 回答
1

在我看来,您可以通过以下方式优化您的表格:

  1. 作为具有 2 个前键的关系表,您不必使用“id”字段。
  2. 在你的桌子上使用“innodb”引擎
  3. 将您的关系表命名为“user_2_food”,这样会更清楚。
  4. 尝试使用尽可能小的数据类型,即“smallint”优于“int”,并且不要忘记“UNSIGNED”属性。
于 2012-11-28T10:34:06.923 回答
0

创建以下三个表将产生有效的设计。

users : userId, username, userdesc
foods : foodId, foodname, fooddesc
userfoodmapping : ufid, userid, foodid, rowstate

rowstate 的意义在于,如果将来用户不喜欢那个食物,它的 state 会变成 -1

于 2012-11-28T06:55:04.520 回答
0

在我的选择中,您有 2 个选项:

  1. 摆脱 ID 字段,但在这种情况下,将其他键(组合)设为主键

  2. 将您的 ID 键作为表的主键。

无论哪种情况,我认为这是一种适当的方法。一旦遇到效率低下的问题,您可能会考虑如何加载表的一部分或任何其他技术。现在就可以了。

于 2012-11-28T06:56:49.907 回答