【问题标题】:Mysql Table and Index Design for Dating Portal [closed]约会门户的Mysql表和索引设计[关闭]
【发布时间】:2013-09-17 19:41:56
【问题描述】:

我正在创建一个约会门户,我们将在其中向用户询问大约 40-50 个问题,例如宗教、种姓、出生日期、食物偏好、吸烟/不吸烟。

我正在就用户偏好提出类似的问题,例如年龄范围、宗教偏好、吸烟偏好。

我有大约 30-40 个这样的偏好。

现在我想根据偏好设置向用户显示匹配项。 我想知道我应该如何设计 MySQL 表和索引。

我应该创建 1 个用户偏好的大表并拥有所有偏好索引。 应该是多列索引还是合并索引。

我是否应该将一组问题保存在不同的表格中并在获取数据时加入它们? 米

【问题讨论】:

  • 这里有一些关于 EAV 的讨论 - 讨论从幻灯片 16 开始。

标签: mysql database database-design solr indexing


【解决方案1】:

我认为这可能是EAV 的情况:

您应该能够按类似于此的降序(从最匹配到最不匹配)获得匹配的用户对:

SELECT *
FROM (
    SELECT U1.USER_ID, U2.USER_ID, COUNT(*) MATCH_COUNT
    FROM USER U1
        JOIN USER_PREFERENCE P1
            ON (U1.USER_ID = P1.USER_ID)
        JOIN USER_PREFERENCE P2
            ON (P1.NAME = P2.NAME AND P1.VALUE = P2.VALUE)
        JOIN USER U2
            ON (P2.USER_ID = U2.USER_ID)
    WHERE U1.USER_ID < U2.USER_ID -- To avoid matching the user with herself and duplicated pairs with flipped user IDs.
    GROUP BY U1.USER_ID, U2.USER_ID
) Q
ORDER BY MATCH_COUNT DESC

这只是通过它们的确切值匹配首选项。您可能希望为范围或类似枚举的值创建额外的“首选项”表,并相应地替换 P1.VALUE = P2.VALUE。如果匹配的是USER表中的数据(比如用户的年龄是否属于其他用户的首选年龄范围),您可能还需要特殊处理。

注意{NAME, VALUE} 上的索引,该索引旨在帮助P1.NAME = P2.NAME AND P1.VALUE = P2.VALUE。 InnoDB 表是clustered,一个后果是二级索引包含PK 字段的副本——在这种情况下,这会导致索引I1 完全成为cover 表。 MySQL 是否会真正使用它是另一回事 - 一如既往地查看查询计划并衡量代表性数据......

【讨论】:

    【解决方案2】:

    我看到这样的东西:

    questions 是要回答的问题列表。 question_type 是一个枚举,指示预期的答案类型(例如,从 question_choices 查找、日期、数字、文本等) - 您希望输入的任何类型的数据。这与此表中的其他列一起,可以驱动您的输入表单。

    question_answers 包含预定义的问题答案列表(例如预定义的宗教列表、头发颜色或眼睛颜色等)。这可用于在您的输入表单上构建值的下拉列表。

    users 很容易解释。

    user_characteristics 包含我对问卷的回答列表。 weight 列表明寻找我的人有相同的答案对我来说有多重要。如果答案来自从question_choices 表构建的选择列表,则将填充question_choices_id。否则 question_choices_id 将为 NULL。 value 列的情况正好相反。如果答案来自从question_choices 表构建的选择列表,value 将为 NULL。否则,value 将包含用户手工制作的问题答案。

    user_preferences 包含我正在寻找的问卷的答案。 weight 列表明我正在寻找的人有相同的答案对我来说是多么重要。 question_choices_idvalue 列的行为与 user_characteristics 表中的行为相同。

    查找匹配项的 SQL 可能类似于:

    SELECT uc.id
          ,SUM(up.weight)                   AS my_weighted_score_of_them
          ,SUM(uc.weight)                   AS their_weighted_score_of_me
          ,SUM(up.weight) + SUM(uc.weight)  AS combined_weighted_score
      FROM user_preferences        up
      JOIN user_characteristics    uc
        ON uc.questions_id           = up.questions_id
       AND uc.question_choices_id    = up.question_choices_id
       AND uc.value                  = up.value
       AND uc.users_id              != up.users_id
     WHERE up.users_id               = me.id
     GROUP BY uc.id
     ORDER BY SUM(up.weight) + SUM(uc.weight) DESC
             ,SUM(up.weight) DESC
             ,SUM(uc.weight) DESC
    

    出于性能原因,建议使用关于 user_characteristics(id、question_id、question_choices_id、value 和 user_id)的索引和关于 user_preferences(id、question_id、question_choices_id、value 和 user_id)的索引。

    请注意,上述 SQL 将为每个用户返回一行,但发出请求的用户除外。这当然是不可取的。因此,可能会考虑添加HAVING SUM(up.weight) + SUM(uc.weight) &gt; :some_minimum_value - 或其他方式来进一步过滤结果。

    进一步的调整可能包括只返回与我一样重视答案的人(即他们的特征体重>=我的体重偏好体重。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 2014-09-12
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多