2

1 个数据库,包含 3 个表:用户-照片-投票
- 一个用户可以拥有多张照片。
- 一张照片可以有很多票。
- 用户可以对多张照片进行投票。
- 一个投票记录:
。结果为 int (-1/disliked, 0/neutral, 1/liked)
。投票的用户的 id。

这是我所拥有的(所有 FK 在删除和更新时都是级联的):http://grab.by/iZYE

sid = surrogate id)

我的问题是:这似乎不对,我已经看了 2 天,不能自信地继续前进。我该如何优化它还是我完全错了?

4

2 回答 2

1

我看到的第一件事是您在表上有重复的唯一 ID。您不需要sid列;只需使用user_id, photo_id, and photo_user_id(也许将这个重命名为vote_id)。那些 ID 列也应该是INT类型,绝对不是VARCHARs。您可能不需要投票总数列photo;您可以在需要时运行查询以获取总数,而不必担心保持两个表同步。

假设您只允许每位用户对每张照片投一票,则可以修改 的结构,因此只有user_idphoto_id和列vote_result。然后,您将使主键成为 ( user_id, photo_id) 上的复合索引。但是,由于您使用的是外键,这使得该表有点复杂。

于 2013-01-14T17:01:31.097 回答
1

MySQL/InnoDB 表总是聚集在一起的(更多关于聚集在这里这里)。

由于主键还充当集群键1,因此使用代理主键意味着您在物理上对表进行排序,这对客户端应用程序没有有用的意义,也不能用于查询。

此外,聚簇表中的二级索引可能比基于堆的表“更胖”,并且可能需要双重查找。

由于这些原因,您希望避免使用代理并使用更多“自然”键,类似于以下内容:

在此处输入图像描述

{USER_ID, PICTURE_NO}在表中VOTE引用了中的同名字段PICTUREVOTE.VOTER_ID引用。如果可以,USER.USER_ID请使用整数*_ID和字段。)*_NO

该物理模型将能够非常有效地查询:

  • 给定用户的图片(对PICTURE主/集群索引的简单范围扫描)。
  • 对给定图片投票(对VOTE主/集群索引的简单范围扫描)。根据具体情况,这实际上可能足够快,因此您不必将总和缓存在PICTURE.

如果您需要给定用户的投票,请将VOTEPK 更改为:{VOTER_ID, USER_ID, PICTURE_NO}如果您需要两者(图片投票和用户投票),请保留现有PK,但在{VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}.


1在 InnoDB 中。在某些 DBMS(例如 MS SQL Server)中,集群键可能与主键不同。

于 2013-01-14T18:34:10.850 回答