8

我正在创建一个像 Tinder 这样的应用程序。用户可以向右滑动或喜欢,向左滑动或不喜欢其他用户。问题是关于存储用户的操作。用户操作需要一个表,如下所示

Person 1.   |   Person 2.    |     op
__________________________________
000001.          000007.          Dislike
000001.          000011.          Like
000001.          000053.          Dislike
000001.          000173.          Dislike

它存储操作,也用于不向用户显示更多次。到现在还可以。

但问题是如果只有 1000 个用户刷另外 1000 个用户,该表将有 1M 行。如果有 100,000 个用户这样做......它会达到 100M 行!这是非常巨大的。

你们对不增长这么大的结构设计有什么想法吗?

谢谢你。

4

3 回答 3

5

有几件事需要考虑。

首先,除非您知道需要运行的查询类型,否则表的大小并不是很有趣。正如其他人所说,拥有数亿行的表没什么好怕的,如果您正在查询可索引字段,您可能可以扩展到数十亿行,而无需通过购买更大更好的硬件来使用奇异的解决方案。因此,一个解决方案,其中 90% 的查询是

select * from users where user_id not in (select interacted_user_id from interactions where interacting_user_id = $current_user) limit 10

我的猜测是,这将在您的笔记本电脑上扩展到数亿行,在体面的服务器上扩展到数十亿行。我的强烈建议是使用简单的关系解决方案,而不使用分区或其他奇特的解决方案,直到您扩展到不再起作用的程度,并且您已经调整了查询​​并尽可能升级了您的硬件。这比任何其他解决方案便宜/容易得多。

更大的挑战将是地理空间方面 - 大概,您希望根据与当前用户的距离对结果进行排序。

您可以对数据进行分区的一种方法是按区域收集“交互”。这需要一些思考 - 您可能不想要“硬”边界,而是有重叠的地理区域。地图上的每个点都可能有几个重叠的“区域”,每个区域都有自己的表格。您在一个区域中拥有的用户越多,重叠的圆圈就越小 - 曼哈顿可能有 3 个区域,格陵兰可能只有 1 个。然后您的查询会查看每个重叠区域的表,并将以前没有的用户联合起来与当前用户交互。

于 2019-03-15T15:35:45.883 回答
4

如果人 1 不喜欢人 2,则无需将人 1 显示给人 2。即使您显示他,他们也永远不会匹配。因此,您的计算 1K x 1K = 1M 有点高估了。

但是,如果您仍然想为两个用户设置喜欢/不喜欢的集合,您可能会考虑这种“压缩”行的可怕想法。

想象一下,你有一个这样的序列:

| Person 1 | Person 2 |  Op       |
| -------- | -------- | --------- |
| 0001     | 1010     |  Dislike  |
| 0001     | 1011     |  Dislike  |
| 0001     | 1012     |  Dislike  |
| 0001     | 1013     |  Dislike  |
| 0001     | 1015     |  Like     |
| 0001     | 1017     |  Dislike  |
| 0001     | 1018     |  Dislike  |
| 0001     | 1019     |  Dislike  |
| 0001     | 1021     |  Like     |

如果您有彼此关注的 id,您可能会将它们显示为

| Person 1 | Person 2 |  Op       | N    |
| -------- | -------- | --------- | ---- |
| 0001     | 1010     |  Dislike  | 3    |
| 0001     | 1015     |  Like     | 0    |
| 0001     | 1017     |  Dislike  | 2    |
| 0001     | 1021     |  Like     | 0    |

其中 N 是序列中的最大 id(例如 1010 + 3 = 1013)。如果将 N 定义为无符号 tinyint,则序列的最大可能大小可以是 255,这意味着,理论上,可以将 255 个连续的不喜欢/喜欢保存为 1 条记录。

查询将是这样的(假设您正在寻找 id 1013):

SELECT a.* 
FROM (
    SELECT *
    FROM `table`
    WHERE person_1 = 0001
      AND person_2 >= (1013 - 255) -- 255 is a max size of a sequense 
      AND person_2 <= 1013
) a
WHERE a.person_2 <= 1013 AND a.person_2 + N >= 1013

子选择将限制可能记录的范围,然后主选择将匹配记录(如果存在)。在这种情况下,它将是

| Person 1 | Person 2 |  Op       | N    |
| -------- | -------- | --------- | ---- |
| 0001     | 1010     |  Dislike  | 3    |

但是,就个人而言,我会选择这个并更喜欢您当前的解决方案,因为它很简单。

或者作为另一种变体,您可以通过这种方式压缩表格

| Person 1 | Person 2 | Max Person 2 |  Op       |
| -------- | -------- | ------------ | --------- |
| 0001     | 1010     | 1013         |  Dislike  |
| 0001     | 1015     | 1015         |  Like     |
| 0001     | 1017     | 1019         |  Dislike  |
| 0001     | 1021     | 1021         |  Like     |
于 2019-03-14T12:47:35.750 回答
1

你永远不会有 100 万行,因为如果你在做一个类似 Tinder 的应用程序,你可以重新匹配人。所以我建议你添加一个日期列来知道你什么时候可以删除行和存储过程,你可以执行它来清理过期的关系。

使用此列,行将不会堆叠,您将永远不会有数百万行。

当人们喜欢在一起时,您也不需要存储。

编辑:为什么不使用两列 CHECKSUM() 来存储每个关系的哈希?它会更轻。

EDIT2:别忘了这是一个爱情应用程序。人们并不适合所有人,因为他们有性取向。

于 2019-03-11T14:06:58.213 回答