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

bla*_*666 7 mysql architecture database-design 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数据库或网络应用程序中设计这个,以便用户可以以系统扩展到超过几千个用户的方式与每个其他用户进行单独评级?

LSe*_*rni 3

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

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

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

其他策略是仅对更有可能进行比较的记录运行主要算法:在您的示例中,“同一城市”。或者在更新记录时(但这需要存储(user_1,user_2,ranking,last_calculated),仅重新计算那些排名较高、非常旧或从未计算过的记录。排名最低的匹配项不太可能发生太大变化而浮动短时间内到达顶峰。

更新

问题还在于使用 O(N^2)存储空间进行操作。

如何减少这个空间呢?我想我可以看到两种方法。一是根本将某些信息放入匹配表中。“匹配”功能越是僵硬和陡峭,就越有意义;拥有一万个“好的匹配”就意味着匹配的意义微乎其微。因此,当 User1 更改某些关键数据时,我们仍然需要进行大量重新计算,以防将 User1 的一些“不”匹配带回“可能”区域。但我们会为每个用户保留一个较小的活跃匹配派系。

存储量仍将呈二次方增长,但增幅较小。

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

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

为此,您可能可以在输入时间(因此在 O(k) 中)将某些数据“映射”到空间信息或字符串并使用编辑距离。

单个用户的存储会增长,但会线性增长,而不是二次增长,而且 MySQLSPATIAL索引非常高效。