像Tinder这样的应用程序的高效MySQL数据库设计

时间:2019-03-11 13:57:54

标签: mysql database data-structures tinder

我正在创建Tinder之类的应用。用户可以向右或向右滑动,向左或向左滑动或不喜欢另一个用户。问题是关于存储用户的操作。像下面这样的用户操作需要一张表

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

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

但是问题是,如果仅1000个用户刷卡另外1000个用户,则该表将具有1M行。如果有100,000个用户这样做,那么……将达到1亿行!很大。

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

谢谢。

3 个答案:

答案 0 :(得分:1)

您永远不会有一百万行,因为如果您正在做类似Tinder的应用程序,则可以重新匹配人员。因此,我建议您添加一个日期列,以知道何时可以删除行和存储过程,并且可以执行该清理清理过期的关系。

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

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

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

EDIT2:不要忘记这是一个爱情应用程序。人们无法与所有人匹配,因为他们有性取向。

答案 1 :(得分:1)

有几件事情要考虑。

首先,表的大小并不是很有趣,除非您知道需要运行的查询类型。就像其他人所说的那样,不必担心具有数亿行的表,并且如果您要查询可索引字段,则可以扩展到数十亿行,而不必使用奇异的解决方案通过购买更大更好的硬件。因此,您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个区域。您的查询将查看每个重叠区域的表,并合并之前未合并的用户与当前用户进行了互动。

答案 2 :(得分:0)

如果人1不喜欢人2,则无需向人2显示人1。即使您显示他,他们也永远不会匹配。因此,您的计算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     |