我正在使用PHP和MySQL制作某种“活动流/提要”。
我为流提供了一个表,它只存储活动的类型和时间戳。然后,我需要查找可在各种表中找到的活动的实际数据(取决于活动类型)。该流应该能够处理数百个用户,因此我需要它才能表现良好。我得到的选项:
我还有其他选择吗?在绩效方面最好的方法是什么?
答案 0 :(得分:4)
您可以使用单个查询执行数据驱动的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行)。我没有正确测试它,因为我缺乏任何数据并且不得不假设,但代码片段应该基本上正常运行。
activities
表中。如果有必要,您可以向相邻表添加额外信息。但是,一般来说,如果多个表使用相同的数据,您可能应该将其移动到主列中,除非绝对不必这样做。
答案 1 :(得分:0)
如果活动流不是太长(几条记录,而不是数千条记录),我只会进行一次查询,如果表格索引正确,查询应该足够快。如果您可以使用表格制作联盟,我想这个查询应该不那么昂贵。
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";
...
您想要获得的结果大小是多少?你想如何订购结果?通过限制查询结果,性能可能不是问题。
答案 2 :(得分:0)
这是一个迟到的回复,但如果活动供稿是较大应用程序的一部分,那么使用像Collabinate(http://www.collabinate.com)这样的外部服务可能是有意义的。
答案 3 :(得分:0)
我实施的解决方案有7种不同类型的内容类型都存储在不同的表格中,但我有 1个活动/供稿表。
我的解决方案 - 使用 mySQL5.7我利用了JSON字段。我有一个工作,它选择不同类型的内容,并在活动表中插入一行,并使用 mysql JSON_OBJECT(),它将数据存储在数据列中的json,然后我的应用程序操纵该json并显示它应该。 JSON数据仅包含该内容类型所需的相关数据,因此没有空值
所以这意味着我没有内部联接,也没有没有可填充空字段的可伸缩表。
我可以轻松添加更多内容类型而无需更改任何内容。