如何提高匹配算法的性能

时间:2017-04-24 07:48:54

标签: algorithm performance firebase firebase-realtime-database

我正在编写一个基于兴趣和位置进行匹配的算法。假设我有这些用户数据

{
    "users": [{
            "location": "Delhi, India",
            "interests": ["Jogging", "Travelling", "Praying"],
            "groups": ["exercise", "travelling", "Praying"]
        },
        {
            "location": "Delhi, India",
            "interests": ["Running", "Eating", "Praying"],
            "groups": ["exercise", "Eating", "Praying"]
        }, {
            "location": "Delhi, India",
            "interests": ["Shopping"],
            "groups": ["Shopping"]
        }
    ]
}

这里他们user1和user2有类似的兴趣“运动”和“祈祷”,而user1和user3没有类似的兴趣。

为了找到类似的兴趣,如果我在收到来自移动应用程序的请求时每次都使用SQL查询,那么超过数百万用户的数据库中的人可能会影响我的数据库性能。

SELECT * FROM users WHERE groups = "exercise" OR groups = "travelling" OR groups = "Praying";

这将检查可能影响我的应用程序性能的每个配置文件。我不想使用这种方法,因为这不会很长时间。我应该使用什么算法才能获得高性能?

3 个答案:

答案 0 :(得分:4)

你可以构建一个inverted index,其中key是'group'中的一个标记(即运动,旅行等),值将是属于该组的用户列表。例如,您的倒排索引看起来像这样:

Key: ListOfValues
Exercise: User1 -> User2
Praying: User1 -> User2
Travelling: User1 -> User3 -> User8 -> User14
Shopping: User3

根据您的空间/时间权衡,您是否需要基于树,位图或基于散列表的倒排索引。

现在当你得到一个新用户时,说User99有组(锻炼和祈祷)你可以快速检索'练习'标记的值(即用户)然后检索'祈祷'标记的值然后最后做这两者的'AND'(交集)。

请注意,第一次运行它将是批处理,但是当您开始获取新用户时,您的运行时间复杂性几乎是恒定的(如果您具有类似压缩位图的智能数据结构,则这将成立您在倒排索引中的“用户”值的发布列表,否则交叉点将不会比O(n)AFAIK快。

答案 1 :(得分:3)

插图

如果你有办法获得完整的兴趣列表(也许你让他们从一组兴趣中选择一个特定的条目),你可以使用简单的矩阵乘法和相应的搜索向量。

编辑:此方法也有效,即只要您正确转置,您就可以将用户映射到群组而不是群组给用户,您可能希望这样做,因为您可能会有远用户多于组,尽管示例在原则上是相同的。

Let groups = [
  1: "exercise" 
  2: "traveling"
  3: "praying"
  4: "eating"
  5: "running"
  6: "shopping"
]

Let U = [
  1 1 1 0 0 0  // user 1
  0 0 1 1 1 0  // user 2
  0 0 0 0 0 1  // user 3
]  

您正在任何

中使用OR
Let V = [
  1  // exercise
  1  // traveling
  1  // praying
  0  // eating
  0  // running
  0  // shopping
]

乘法:

U · V = [
  3  // user 1 is in all 3 groups => match
  1  // user 2 is in one group => match
  0  // user 3 is in no groups => no match
]

这会检查每个用户是否存在一个或多个请求的列(OR),并且结果向量中的任何非零条目都是匹配的。

或者,使用相同的确切查询,仅选择具有2个或更多列(AND)的特定集合的用户将匹配为结果向量中的任何 n 或更高值的条目,其中< em> n 是参数的数量。

仅选择具有一个或多个列且一个或多个其他列(XOR)的列将仅视为与正好为<值的结果条目匹配。< / p>

这真的是个好主意吗? 这种方法可以 使用 如果您认为真正的问题是查询可能变得足够复杂,以至于查询分析器将成为瓶颈,查询将变得非常难以管理,或者你需要处理一个不断更改的&#39;组的列表,或者如果你只是打算在你的应用程序中做很多线性代数。

解决方案首先取决于您的用例。例如,如果查询速度至关重要且数据传输不是问题,这种方法将允许一个非常简单的查询返回所有(使用LIMIT)行,然后您可以最佳地筛选直到找到数量为止您希望用于给定页面的用户,仅在必要时运行后续查询以加载更多页面。由于您在每次收到来自移动应用程序的请求时都提到过这种情况,或许您最好每次都缓存可管理数量的用户并轮询此数据而不是数据库,除非找不到匹配项,执行适当的时间测试缓存替换算法(也可能在某种程度上卸载到客户端)。

<强>结论/ TL;博士 这里重要的内容是您想要的结构完全取决于您的应用程序的业务需求。您可以根据需要将数据结构视为深奥,以提高性能,但这通常不如仅使用经过时间考验的解决方案(如基本缓存)那么富有成效。

如果您认为像Yavar建议的倒置键方法的重构最适合您的需求,那么这可能是您的解决方案。

如果您认为图形数据库是必要的,将满足您的业务需求,并且更快,更易于管理,这可能是您的解决方案。

如果您的需求如此具体,以至于您需要完全针对您的应用程序优化的完全特定的自定义实现,而不一定在其他地方有用,那么这可能是您的解决方案。

设计标准存在的原因很多,但优化可能偶然是特定于域的。正如您所看到的,有几种可能的解决方案,但选择最适合您的解决方案取决于许多未知因素,例如业务需求,最终正确的解决方案将是足够快速而不牺牲可维护性/理智/头发。

答案 2 :(得分:1)

数据结构看起来好像是像MongoDb一样的NoSql db。无论如何,检查全文索引是否对您有所帮助。我刚看到MSSQL中的FULL TEXT INDEX(https://docs.microsoft.com/en-us/sql/t-sql/statements/create-fulltext-index-transact-sql)。我之前不知道这件事。 MongoDb也有全文索引。如果正确实施,索引肯定会帮助您的查询。我不确定在一个表上可以实现多少全文索引。请研究一下。