Php 多对多vs一行

Php 多对多vs一行,php,mysql,Php,Mysql,我感兴趣的是,多对多关系如何以及为什么比将信息存储在一行更好 示例:我有两个表,用户和电影(非常大的数据)。我需要建立一种关系“观点”。 我有两个想法: 在Users表中创建另一个名为“views”的列,我将在其中以字符串形式存储此用户已观看的电影的ID。例如:“2,5,7…”。然后我将用PHP处理这些信息 创建新表users\u movies(多对多),其中包含user\u id和movie\u id列。user\u id=5和movie\u id=7的行表示用户5已观看了movie 7 我感

我感兴趣的是,多对多关系如何以及为什么比将信息存储在一行更好

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

  • 在Users表中创建另一个名为“views”的列,我将在其中以字符串形式存储此用户已观看的电影的ID。例如:“2,5,7…”。然后我将用PHP处理这些信息
  • 创建新表users\u movies(多对多),其中包含user\u id和movie\u id列。user\u id=5和movie\u id=7的行表示用户5已观看了movie 7

  • 我感兴趣的是哪种方法更好,为什么。请考虑数据是相当大的。

    < P>第二种方法在各个方面都比较好。您不仅可以利用DBs索引更快地查找记录,还可以使修改变得更容易。

    方法1)可以通过使用类似于“
    …field\u in_set(movie\u id,User\u movielist)…
    ”的SQL来回答“哪些电影有用户X观看”的问题。但另一种方法(“哪个用户看过电影x”)在sql基础上不起作用


    这就是为什么我总是选择方法2):清晰的规范化结构,两种方法都是简单的连接。

    这正是您的需要。若您需要性能,那个么您必须接受信息的冗余并添加一列。如果您的主要目标是尊重规范化范式,那么您不应该有任何冗余。 当我不得不做这种选择时,我会尝试估计冗余的空间损失与感兴趣的查询频率及其性能的关系。

    还有一些想法

    在您的第一种情况下,如果您查找特定用户,您可以很容易地获得他们看过的电影的ID列表。但是接下来需要一个单独的查询来获取详细信息,比如那些电影的标题。这可能是一个在id列表中使用的查询,或者每个电影id一个查询。这将是低效和笨拙的

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

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

    SQL中有很多方法可以分割逗号分隔的值列表,但是这些方法很混乱,任何必须维护这些代码的人都会讨厌它

    这些都是软糖。使用第二种解决方案,这些操作很容易完成,任何结果连接都可以很容易地使用索引(整个查询可能只使用索引,而不涉及实际数据)


    第一种解决方案的另一个问题是数据完整性。您必须手动检查一部电影是否不会为用户出现两次(使用第二种解决方案,可以使用唯一的密钥轻松强制执行)。您也不能仅仅添加外键来确保用户的任何电影id确实存在。此外,您还必须手动确保没有任何内容在分隔的ID列表中输入字符串。

    想象一下:如果您想创建一个看过特定电影的用户列表,或者只计算看过该电影的用户数量,该怎么办?您必须获取所有数据,然后循环使用它来过滤看过该电影的用户。特别是由于您将拥有大量数据,这将不是非常有效。这就是关系数据库被发明的原因。方法一类似于尝试“unsqlize”sql数据库