用于n *(n - 1)/ 2算法的MySQL架构

时间:2012-10-01 19:45:30

标签: mysql database-design architecture scalability

我目前正在开发一个网站,用户可以根据属性(年龄,身高,城镇,教育等)搜索其他用户。我现在想在用户配置文件之间实现某种评级。基于2个给定配置文件之间的相似性,通过其自己的算法计算评级。例如,用户A的用户B评级为“匹配评级”85,用户C评级为79。 B和C的评级为94等等......

用户应该能够搜索某些属性并按评级过滤结果。

由于评级因个人资料而异,并且还取决于用户进行搜索,因此我不能简单地将字段添加到我的用户表并使用ORDER BY。到目前为止,我想出了两个解决方案:

  • 我的第一个解决方案是每晚进行批处理作业,计算每个可能的用户组合的评级,并将其存储在单独的表(user1,user2,rating)中。然后,我可以使用用户表加入此表,并按评级顺序排列结果。在做了一些数学运算后,我认为这个解决方案不能很好地扩展。

    根据公式n *(n - 1)/ 2,10个用户有45种可能的组合。对于1.000用户,我突然需要在我的评级表中插入499.500个评级组合。

  • 第二个解决方案是让MySQL离开并在我的应用程序中即时计算评级。这也不能很好地扩展。假设搜索应该只返回100个结果到UI(顶部评分最高)。如果我有10.000个用户并且我想搜索生活在纽约的每个用户按等级排序,我必须将每个居住在纽约的用户加载到我的应用程序中(假设为3.000),应用算法然后仅返回前100名给用户。这样我就从数据库中加载了2.900个无用的用户对象,并在算法上浪费了CPU而没有对它做任何事情。

我可以在我的MySQL数据库或网络应用程序中设计这些内容的任何想法,以便用户可以以系统扩展到超过几千个用户的方式对每个其他用户进行单独评级吗?

3 个答案:

答案 0 :(得分:3)

如果必须将每个用户与其他所有用户进行匹配,则算法为O(N ^ 2),无论您做什么。

如果您可以利用某种一维"指标",那么您可以尝试将每个用户与一个合成值相关联。但那很尴尬,可能是不可能的。

但您可以做的是注意哪些用户在其个人资料中需要更改(无论何时匹配所基于的任何参数,都会发生变化)。此时,您可以仅为这些用户批量重新计算表,从而在O(N)中工作:如果您有10000个用户且只有10个需要重新计算,则必须检查100,000个记录而不是100,000,000个。

其他策略是仅对比较有可能被比较的记录运行主算法:在您的示例中,"相同的城市"。或者在更新记录时(但这需要存储(user_1,user_2,排名,last_calculated),只重新计算排名较高,非常老或从未计算过的记录。排名最低的匹配不会发生太大变化它们会在短时间内漂浮到顶部。

<强>更新

问题还在于使用O(N ^ 2)存储空间

如何减少这个空间?我想我可以看到两种方法。一个是将一些信息放在匹配表。 &#34;匹配&#34;功能越有意义就越坚硬陡峭;有一万个好的比赛&#34;意味着匹配意味着很少。因此,当User1更改某些关键数据时,我们仍然需要重新计算,以防它带来一些User1&#34; no-no&#34;回到&#34;也许&#34;区。但是我们会为每个用户保留一小部分活动匹配。

存储仍然会以二次方式增长,但不会那么陡峭。

另一种策略是重新计算匹配,然后我们需要开发一些方法来快速选择哪些用户可能具有良好匹配(从而限制了检索到的行数) JOIN),以及一些快速计算匹配的方法;这可能需要以某种方式将User1和User2之间的匹配重写为DataUser1,DataUser2子集的一个非常简单的函数(可能使用辅助列)。

挑战在于利用MySQL功能并卸载MySQL引擎的一些计算。

为此目的,你或许可以&#34;映射&#34;一些数据,在输入时间(因此在O(k)中),空间信息或字符串并使用Levenshtein距离。

单个用户的存储空间会增长,但会以线性方式增长,而不是按字母方式增长,而且MySQL SPATIAL索引非常有效。

答案 1 :(得分:2)

如果搜索只返回前100名最佳匹配,那么为什么不存储这些呢?听起来你绝不想要搜索结果的底端,所以不要计算它们。

这样,您的存储空间只有o(n),而不是o(n ^ 2),并且更新也应该是。如果有人真的想看到前100个匹配(并且你想让它们),那么你可以选择在那时实时运行查询。

答案 2 :(得分:0)

我同意@Iserni所说的一切。

如果您有一个Web应用程序并且用户需要“登录”,那么您可能有机会在那时创建该用户的排名并将它们存储到临时表(或现有表中的行)中。

如果计算所需的所有数据都适合内存,这将在合理的时间(几秒钟)内工作。然后,数据库引擎应该进行全表扫描并创建所有评级。

对于一个登录的用户来说,这应该可以很好地工作。可以两个人通过。 。 。但是,如果你有十几个用户在一秒钟内登录,它就无法很好地扩展。

但从根本上说,您的评分不能很好地扩展。您必须将所有用户与所有用户进行比较才能获得结果。无论是批量(在夜间)还是实时(当有人查询时)都不会改变问题的性质。它将使用大量的计算资源,同时发出请求的多个用户将成为瓶颈。