多对多对一排

时间:2015-02-03 15:41:36

标签: php mysql

我很感兴趣,为什么多对多关系比将信息存储在一行中更好。

示例:我有两个表,用户和电影(非常大的数据)。我需要建立一个关系“视图”。 我有两个想法:

  1. 在“用户”表格中创建另一个名为“views”的列,我将在该字符串中存储此用户查看过的电影的ID。例如:“2,5,7 ......”。然后我将用PHP处理这些信息。
  2. 使用user_id和movie_id列创建新表users_movies(多对多)。 user_id = 5且movie_id = 7的行表示用户5已查看电影7。
  3. 我感兴趣的是哪种方法更好,为什么。请考虑数据非常大。

4 个答案:

答案 0 :(得分:1)

第二种方法几乎在所有方面都更好。您不仅可以利用数据库索引更快地查找记录,还可以使修改变得更加容易。

答案 1 :(得分:1)

方法1)可以通过使用像“...field_in_set(movie_id, user_movielist) ...”这样的SQL来回答“哪些电影有用户X观看过”的问题。但反过来说(“哪个用户确实看过电影x”)将无法在sql基础上运行。

这就是为什么我总是采用方法2):明确规范化结构,两种方式都是简单的连接。

答案 2 :(得分:0)

这只是你的需求。如果您需要性能,则必须接受信息的冗余并添加一列。如果您的主要目标是尊重规范化范例,那么您根本就不应该有冗余。 当我必须做这种选择时,我会尝试估计冗余的空间损失与感兴趣的查询的频率及其性能。

答案 3 :(得分:0)

还有一些想法。

在您第一种情况下,如果您查找特定用户,您可以轻松获取他们所看到的电影的ID列表。但是,那么需要一个单独的查询来获取这些电影的标题等细节。这可能是一个查询使用IN与id列表,或每个电影ID一个查询。这将是低效和笨重的。

使用MySQL,可能会使用FIND_IN_SET()函数加入这种情况(尽管这样做的一个缺点是你正在考虑非标准SQL)。您可以使用ON FIND_IN_SET(film.id,users.film_id)>将您的电影表加入到用户手中。 0。然而,这不会使用连接的索引,并且涉及一个函数(虽然快速执行它的操作,但在数千行上执行时会很慢)。

如果你想找到所有观看过特定用户观看过的电影的用户,那就更难了。您不能只使用FIND_IN_SET,因为它需要单个字符串和逗号分隔列表。作为单个查询,您需要将特定用户加入到电影表中以获取大量中间行,然后再次将其连接到用户(使用FIND_IN_SET)以查找其他用户。

SQL中有一些方法可以拆分以逗号分隔的值列表,但它们很混乱,任何必须维护此类代码的人都会讨厌它!

这些都是软糖。使用第二个解决方案,这些操作很容易,而且任何生成的连接都可以轻松使用索引(并且可能整个查询只需使用索引而无需触及实际数据)。

第一个解决方案的另一个问题是数据整合。您必须手动检查胶片是否为用户显示两次(使用第二种解决方案,可以使用唯一键轻松实施)。您也不能只添加外键以确保用户的任何电影ID确实存在。此外,您必须手动确保在分隔的ID列表中没有任何内容输入字符串。