优化mysql查询以获取每个用户的“不可见”条目

这个称号是相当迷人的,但我不能拿出更清楚的东西。

长话短说,我们正在创build一个连接到与mySql数据库通信的node.js服务器的移动应用程序。 很常见的设置。 现在,我们有多个用户可以上传“时刻”到我们的服务器。 所有其他用户只能看到这些时刻。

只要用户x看到另一个用户的时刻,x就永远不会看到这个时刻。 也许有点像Snapchat,除了单一用户而不是单一用户。 矩也按照当前用户的位置按距离sorting。

现在,我正在寻找一种仅从数据库中提取“看不见”时刻的智能方式。 现在,我们使用Users和Moments之间的关系表。

假设一个用户(ID = 20)看到了一个时刻(ID = 30320),那么我们插入到这个表格20和30320中。我知道。 这难以扩展,可能是一个可怕的想法。

我想可能是检查最后一次看到的date,只取得过去这个日子的时刻,但是再一次,在按datesorting之前,时刻是按距离sorting的,所以有可能看到一个3分钟的时刻,然后是那个时刻是30秒老。

有没有更聪明的做法,或者我注定要使用Moments和Users之间的关系表,并在查询时join到它?

非常感谢。

编辑 –

这个逻辑总共使用3个表格。

  • 用户
  • 时刻
  • MomentSeen

MomentSeen只包含用户已经看到什么时刻,什么时候。 由于时间不是按datesorting的,我无法获取上次看到的时刻之后上传的所有时刻。

编辑 –

我刚刚意识到移动应用程序Tinder必须使用类似的逻辑,用户“喜欢”哪个用户。 既然你不能回头再看到一个用户两次,他们可能会使用一个非常相似的查询,我正在寻找。

考虑到他们有很多的用户,而且他们是按照距离和其他一些未知的标准sorting的,那么与“UserSawUser”关系表相比,必须有更聪明的做事方式。

编辑

我不能提供整个数据库结构,所以我只是留下重要的表格和他们的一些领域。

Users { UserID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY } Moments { MomentID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, UploaderID INT UNSIGNED, /* FK to UserID */ TimeUploaded DATE /* usually NOW() while insertion */ } MomentSeen { /* Both are FK to Users and Moments */ MomentID INT UNSIGNED, UserID INT UNSIGNED } 

您可以考虑实施布隆filter。 它被广泛用于减less磁盘search和驱动更好的性能。

Medium正在使用它来检查用户是否已经阅读了post。

更多细节在这里 –
https://medium.com/the-story/what-are-bloom-filters-1ec2a50c68ff https://en.wikipedia.org/wiki/Bloom_filter

不要为每个用户使用一个表。 有一个单一的表的时刻。

“时刻”似乎有两个相互冲突的sorting:“距离”和“看不见”; 这是什么?

如果是“看不见的”,“时刻”是按时间顺序编号的? 这意味着每个用户都有一个last_moment_seen在此之前的所有Moments都被看到了; 所有之后都没有见过。 所以…

 SELECT ... WHERE moment > ( SELECT last_moment_seen FROM Users WHERE user_id = $user_id ); 

会得到给定用户尚未看到的所有时刻。

蒙了一会儿; 回来了更多的build议。

编辑

这应该给你没有看到的时刻。 您可以根据需要订购。

 SELECT m.... FROM Moments m LEFT JOIN MomentSeen ms ON ms.MomentID = m.MomentID WHERE ms.MomentID IS NULL ORDER BY ... LIMIT 1 -- if desired 

为什么犹豫在使用join? 你有没有试图用虚拟数据填充你的数据库。 他们中的数百万能够衡量你的系统对性能的影响?

使用连接并不是一个坏主意,如果做得对,通常比单个表更快。

您应该对数据库devise进行研究,以提供一些参考。

例如,使用索引来完成表格的sorting。 但是,您可以在一个表上使用多个索引,并在每个索引中使用一个列的组合。 这可以通过分析对表经常使用的查询来完成。 一个方便的配方是通过创build包含连接键中使用的一组列的索引,针对每个可能的“where”参数组合作为一组列索引的另一个索引,以及针对每个“order”查询运行的一组索引列对那张桌子(升序/降序确实重要)。

所以不要害羞添加另一列和索引,以满足您的需要。

如果你谈论可伸缩性,那么你应该考虑调整数据库引擎。 例如。 使用大整数可能产生更高的关键。 使用数据库集群设置还需要深入分析,因为自动增量键在多主设置中有问题

如果你试图从你的系统中获得更多的性能,那么你应该考虑将整个数据库从一开始就devise为表分区友好的。 这将包括认真分析您的业务规则。 创build一个表分区友好的环境需要设置一系列的键作为关键,并物理分割数据(记住在mysqlconfiguration文件中设置file_per_table = 1,否则表分区的好处丢失)如果不正确,分区将对你没有任何好处

https://dev.mysql.com/doc/refman/5.5/en/partitioning.html