如何在此发布系统中超过64个通道(位)

时间:2014-11-26 23:47:55

标签: php mysql performance bit-manipulation

编辑:

在下面的问题中,我简化了我的问题,因此很容易解释。我现在可以看到,基于前几条评论,我已经过度简化了它。因此,当您通读时,请记住这一新事实:系统中的发布者几乎与用户一样多,每个发布者都可以拥有自己的列表(最好是数千个)兴趣组。简而言之,请注意速度很重要,简单的列表只是不会削减它......

结束编辑。

我正在设计一个使用MySQL和PHP向用户发布帖子(博客文章)的系统。帖子发布到'兴趣小组'并且用户注册以阅读特定兴趣小组。当用户请求他们的新闻提要时,我需要能够尽快汇编并返回文章列表。

为了速度,我使用按位运算符从数据库中选择帖子。每个兴趣组对应于整数中的位。每个帖子都有一个“发布掩码”,这是一个整数,用于存储发布它的组。每个用户作为“读取掩码”,这是一个存储用户感兴趣的组的整数。

举例来说,兴趣小组可能如下:

  • 第0位(小数1):钓鱼
  • 第1位(小数2):布什行走
  • 第2位(小数4):Sky Diving

在这种情况下,帖子的发布掩码可能是,例如' 3' (钓鱼和布什散步)。读掩码为' 5'的用户(钓鱼和跳伞)可以访问该文章,但是具有“4' 4”读掩码的用户可以访问该文章。不会。帖子的选择发生在SQL查询中。查询只是使用一个WHERE子句,它返回用户的读掩码和每个帖子的发布掩码之间的按位AND的布尔结果。

所以......除了明显的问题外,这个工作非常顺利:我只限于64个兴趣小组。对于我的生活,我无法想到它周围的优雅方式。

我可以添加第二对蒙版并将WHERE子句基于((PubMask1 AND ReadMask1) || (PubMask2 AND ReadMask2))但是这个线性'方法只给我128组。如果我想要3000,那会怎么样?

我查看了PHP GMP库但是没有帮助 - 我不想从数据库中提取所有内容以在PHP中过滤它 - 我无法找到任何GMP - 等效的MySQL插件。 (除此之外,我不确定多个精度库的速度是多少)。

我还有其他可能性吗?例如,有没有办法存储一个长的长串零和一串的二进制算法?

一种可能的解决方案是使用如上所述的掩码对(PubMask1,PubMask2,ReadMask1,ReadMask2),并让每个帖子记录具有多个发布记录(并且每个用户具有多个读掩码记录)。在这种情况下,我可以拥有多达64 x 64个兴趣小组,但如果我能提供帮助,我真的不想在这个高性能方案中引入一对多的关系。

1 个答案:

答案 0 :(得分:1)

你在这里提出的建议是深入深入的兔子洞,实际上不会产生任何性能提升。事实上,它可能会产生相反的效果,使您的架构不仅令人讨厌使用,而且由于您的非标准标记方法而导致性能问题瘫痪。在像MySQL这样的RDBMS中,你越是反对谷物,你就会越多地受到性能问题的惩罚。

这种方法是通过一个简单的关联表将帖子链接到组:

CREATE TABLE post_group_links(
  id INT AUTO_INCREMENT PRIMARY KEY,
  post_id INT NOT NULL,
  group_id INT NOT NULL,
  UNIQUE KEY `index_pgl_post_group` (`post_id`,`group_id`)
);

UNIQUE索引约束意味着您可以在帖子和组之间只有一个关联。像MySQL这样的数据库使获取组的所有文章变得微不足道和快速:

SELECT posts.* FROM posts
  LEFT JOIN post_group_links ON posts.id=post_id
  WHERE post_group_links.group_id=?

即使是大型数据库也应该以毫秒为单位运行,因为索引会处理它。如果您想订购这些帖子,您可能需要在连接表中添加某种排序数据,但添加并合并到索引中这是微不足道的。

如果您想使用独占AND查找多个论坛中的帖子,那么它也可以,但速度较慢,大致如下所示:

SELECT posts.* FROM posts
  LEFT JOIN post_group_links ON posts.id=post_id
  WHERE post_group_links.group_id IN (?,?,?)
  GROUP BY posts.id
  HAVING COUNT(post_group_links.id)=3

有很多方法可以编写它,包括使用子查询,如果这样可以更容易理解。

这可以轻松扩展到数千个群组中的数百万个帖子。一个现代的SSD支持的MySQL服务器甚至不会像每分钟数千次那样破坏运行查询,并且可以使用更高级的技术(如分区或水平分片)进行调整以更快地运行。

您提出的涉及少数64位列的解决方案直接违反了重要的Zero, One or Infinity Rule。像PubMask1PubMask2这样的列几乎总是是具有基本设计问题的架构的确定标志。

相关问题