【问题标题】:MYSQL,PHP,MEMCACHED - Display recent 20 posts along with recent four commentsMYSQL、PHP、MEMCACHED - 显示最近的 20 篇文章以及最近的 4 条评论
【发布时间】:2012-10-31 14:57:58
【问题描述】:

我正在分析显示最近 20 个帖子以及每个帖子的最新 4 个 cmets 的不同方法。这是一些类似于 facebook 墙的东西,但不会有喜欢、分享和任何其他的东西

示例表结构

帖子
  • p_id = 该帖子的编号
  • user_id = 他们正在发布的用户
  • poster_user_id = 发帖人
  • post
厘米
  • comment_id = 该评论的数量
  • post_id = 评论相关的帖子编号
  • commenter_user_id = 发表评论的人
  • comment

我想到了这些方法

1) 查询 POST 表并获取最近的 20 个帖子,将帖子 ID 发送到数据库并从 COMMENT 表中获取 cmets。但是对于这个总调用数将是

1(posts)+20(cmets)=21 次数据库调用

2) 加入 POST 和 COMMENT 表并获取最近 20 个帖子的所有 cmets,并在显示前一个 POST_ID 时检查,如果相同则不显示帖子,而只显示评论.但是这种做法

得到很多不必要的数据

3) 查询 POST 表并获取最近的 20 个帖子,获取帖子 ID,动态构造 cmets 查询(在 PHP 中创建以下类型的查询)

 SELECT comment FROM comments WHERE post_id=<1st latest_id> ORDER BY comment_id desc LIMIT 4
UNION ALL
 SELECT comment FROM comments WHERE post_id=<2nd latest_id> ORDER BY comment_id desc LIMIT 4
UNION ALL
 SELECT comment FROM comments WHERE post_id=<3rd latest_id> ORDER BY comment_id desc LIMIT 4
....................up to 20 

这里只有

1(posts)+1(comment) = 两次数据库调用

这种方法看起来不错

4) 使用第三种方法并将结果存储在 memcached 中一分钟或 30 秒。如果用户发表任何评论或新帖子,请使用 jquery 并在浏览器中更新他的条目。如果他按下刷新,则向服务器发送一个标志以再次查询数据库并将它们存储在 memcached 中。

这种方法在一分钟内只需要 1 或 2 次数据库调用,但用户再次获取一分钟前发布的数据,而不是最近的数据.. 这对于常规论坛来说很好

5) 即使不是每分钟查询数据库,第一次从数据库中获取前 20 个帖子并将它们与 cmets 一起保存在 memcached 中。每当用户写新帖子时,从 memcached 中删除第 20 个帖子并将新帖子添加为第 1 个顶部帖子。同样对于 cmets 删除第 4 条评论并将新评论附加到帖子中。但这需要一个开发工作。当然,我们必须将记录保存到数据库中(或者在需要时可以遵循一些组提交)。

如果我们编码完美,这对我来说似乎是最好的方法

任何人有任何其他方法或任何好的链接来实施第 5 种方法? (更新内存缓存)

感谢大家的帮助

【问题讨论】:

  • 您不需要 21 次数据库调用,您需要 2 次,总计和 memcache 那些。为 SQL 创建一个hash,这可以是您的唯一键。更新某些内容时,您可以强制重置这些键。保持约定。它会让你以后不用写不必要的代码。
  • 感谢 bigman 的评论。是的更新我可以再次查询数据库,但我所说的第 5 种方法甚至没有调用数据库,即使有任何数据库更改

标签: php mysql memcached


【解决方案1】:

使用user variable诡计:

SELECT   post_id, comment_id
FROM     (
  SELECT   post_id, comment_id,
           @i := IF(@type <=> post_id, @i+1, 0) AS comment_number,
           @p := post_id
  FROM     comments NATURAL JOIN (SELECT * FROM (
             SELECT p_id AS post_id FROM posts ORDER BY p_id DESC LIMIT 20
           ) z) z, (SELECT @type:=NULL) init
  ORDER BY post_id DESC, comment_id DESC
) t
WHERE    comment_number < 4
ORDER BY post_id DESC, comment_id DESC

这仍然需要从所有这些帖子的 cmets 中填充一个临时表 t,然后过滤(在最外面的查询中)仅前 4 个。可以通过在 @987654324 上适当排序的复合索引来避免这种情况@:

SELECT   post_id, comment_id,
         @i := IF(@type <=> post_id, @i+1, 0) AS comment_number,
         @p := post_id
FROM     comments FORCE INDEX (index_name) NATURAL JOIN (SELECT * FROM (
           SELECT   DISTINCT post_id
           FROM     comments
           ORDER BY post_id DESC
           LIMIT    20
         ) z) z, (SELECT @type:=NULL) init
GROUP BY post_id DESC, comment_id DESC
HAVING   comment_number < 4

【讨论】:

  • +1,这对 SQL 的使用令人印象深刻,添加到收藏夹。
  • @eggyal 我知道这是一个复杂的解决方案,但您认为这会带来什么样的性能提升?对于他正在尝试做的事情,您可以对帖子的更新运行一些查询,以准确地重新缓存他想要的内容,并且可能与您在上面所做的成本相同。想法?
  • @bigman:如果没有关于细节的大量信息(包括硬件配置、服务器设置等),就不可能进行精确的性能比较。最好进行基准测试并找出答案。
  • 我意识到精确的性能比较是不可能的,只是询问您对什么更实用的想法;)“就个人而言”,我会设置一个 php 守护程序(矫枉过正,是的,但我喜欢它们)轮询数据库并运行更新脚本。会非常无缝且快速。
  • @eggyal :- 我认为在 (post_id, comment_id) 上创建复合主键支持降序索引。请对此发表评论..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多