【问题标题】:Activity feed with PHP MySQL使用 PHP MySQL 的活动提要
【发布时间】:2011-09-16 13:06:21
【问题描述】:

我正在使用 PHP 和 MySQL 制作某种“活动流/提要”。

我得到了一个流表,它只存储活动的类型和时间戳。然后我需要查找可以在各种表中找到的活动的实际数据(取决于活动类型)。该流应该能够处理数百个用户,因此我需要它来表现良好。我得到的选项:

  • 获取流表 - 在 PHP 中使用某种开关循环,然后调用 SQL 以获取适当的活动数据(针对每个活动)。 (慢)
  • 用一些连接创建一个大 SQL 语句,在一个请求中获取所有活动数据。仍在 PHP 中进行切换,但无需再次调用 SQL。 (对于大桌子来说这会不会很慢?)
  • 在 MySQL 中使用某种视图 - 我以前没有这样做过。
  • 使用多个 SQL 调用来获取所有活动数据并将它们存储在 PHP 数组中,然后从那里进行切换。

我还有其他选择吗?就性能而言,最好的方法是什么?

【问题讨论】:

    标签: php mysql performance feed


    【解决方案1】:

    您可以使用单个查询执行数据驱动的JOIN。本质上,您将 JOIN 每个需要的子表,然后通过别名从您需要的表中选择内容。假设 1 是 activity_drink,2 是 activity_eat,3 是 activity_sports,并且所有子表都有 content 列,您要获取该列:

    SELECT a.`timestamp`,
        CASE a.`activity_type`
            WHEN 1 THEN ad.`content`
            WHEN 2 THEN ae.`content`
            WHEN 3 THEN asp.`content`
        END AS content
    FROM activities AS a
    LEFT JOIN activity_drink AS ad ON (ad.`activity_id` = a.`activity_id`)
    LEFT JOIN activity_eat AS ae ON (ae.`activity_id` = a.`activity_id`)
    LEFT JOIN activity_sports AS asp ON (asp.`activity_id` = a.`activity_id`)
    

    这基本上会在选择时使您的表非规范化。您还可以将其转换为 VIEW 以便于访问。假设您已经正确设置了外键、ID 和/或UNIQUE 索引,它应该不会太贵(MySQL 会注意到表中没有匹配的行并“忽略它” - 选择 NULL 行)。我没有完全正确地测试它,因为我缺乏任何数据并且不得不假设,但 sn-p 应该基本上可以正常工作。

    不过,我想提一下,我个人对必须进行数据驱动的联接持谨慎态度。在这种情况下进行规范化的正确方法是找到最大的公共属性集并将它们放入activities 表中。如有必要,您可以向相邻表添加额外信息。但是,一般来说,如果多个表使用相同的数据,您可能应该将其移到主列中,除非绝对必要不这样做。

    【讨论】:

      【解决方案2】:

      我实施的解决方案有 7 种不同类型的内容类型都存储在单独的表中,但我有 1 个活动/供稿表

      我的解决方案 - 使用 mySQL5.7 我利用了 JSON 字段。我有一项工作,它选择不同类型的内容并将一行插入到活动表中,并使用 mysql JSON_OBJECT() 将该数据作为 json 存储在数据列中,然后我的应用程序就可以操作它json 并按应有的方式显示。 JSON 数据仅具有该内容类型所需的相关数据,因此没有空值

      • 标识 |内容类型 |数据(JSON) |创建 |状态

      所以这意味着我没有内部连接,没有包含大量空字段的不可扩展表。

      我可以轻松地添加更多内容类型而无需更改任何内容。

      【讨论】:

        【解决方案3】:

        如果活动流不是太长(几条记录,而不是几千条),我会只进行一次查询,如果表的索引正确,那么查询应该足够快。以防万一,您可以与您的表进行联合,我想这个查询不应该那么昂贵。

        SELECT * FROM (
          SELECT * FROM stream 
            INNER JOIN type1 ON stream.id = type1.stream_id
          LIMIT 50
        
          UNION
        
          SELECT * FROM stream 
            INNER JOIN type1 ON stream.id = type1.stream_id
          LIMIT 50
        
          UNION
        
          ...
        )
        ORDER BY stream.timestamp_field
        LIMIT 50
        

        作为另一种解决方案,如果您没有很多类型表,您可以对每种表类型进行查询,然后合并结果。但是您必须使用 PHP 对合并的结果进行排序。

        $sql1 = "SELECT * FROM stream INNER JOIN type1 ON stream.id = type1.stream_id";
        $sql2 = "SELECT * FROM stream INNER JOIN type2 ON stream.id = type2.stream_id";
        ...
        

        你想得到多大的结果??你想如何订购结果?通过限制查询结果,性能可能不是问题。

        【讨论】:

        • 感谢您的回复。首先,我不认为 UNION 可以解决问题,因为我的活动数据表非常不同。这就是我加入所有表格的原因(给了我很多列)。我的猜测是数百名用户的活动流可能有 50-100 行。排序只是按时间戳。
        • 如果表的索引正确,那么查询结果不会那么大。您可以毫无问题地加入表格。如果可能,尽量限制结果。
        【解决方案4】:

        这是一个较晚的回复,但如果活动源是更大应用程序的一部分,则使用 Collabinate (http://www.collabinate.com) 等外部服务可能是有意义的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-29
          • 2012-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多