【问题标题】:Fastest way to calculate pairwise comparison on 200k row MySQL database在 200k 行 MySQL 数据库上计算成对比较的最快方法
【发布时间】:2013-01-28 02:56:35
【问题描述】:

我有 200k 列表存储在 MySQL 数据库中。给定一个列表 A,我需要计算 A 和 200k 个列表中的每个列表 X 之间的相似度分数。假设相似度度量很简单,例如 A 和 X 的集合交集的长度。

鉴于成对比较的性质,我想不出为此改进 O(N) 的方法,因此改进运行时意味着使用多个 CPU 内核。现在,我使用 multithreading.Pool() 将这个任务拆分为 4 个内核,但仍然需要将近 10 分钟才能完成。更糟糕的是,我的电脑会关闭以保护自己。

对于以前处理过此问题的任何人,您有其他方法可以分享吗?

【问题讨论】:

  • “列表”是什么意思?
  • 什么时间最长?从数据库中获取数据?实际计算?如果您已经在使用所有内核进行计算,则没有更多 CPU 可使用,因此您唯一的选择是加快计算速度,可能通过计算一些关键指标,如果您已经知道列表是允许您跳过计算的太不一样了。
  • FWIW,如果您使用的是 MySQL,那么总工作可能会受到 IO 限制。这意味着 Python 计算步骤不会占用大部分时间。 FastestWay(tm) 是创建一个单独的 SQL 语句来完成所有工作,并且只返回更好的匹配列表。换句话说,解决方案并不是真正的 Python 问题 ;-)

标签: python


【解决方案1】:
def bestmatch(A, lists):
     a = set(A)
     return min(lists, key=lambda x:  len(set(x) & a)

使用 min 循环 C 速度。 lambda 是一个快速引用 a 的闭包。 set(A) 步骤只计算一次,而不是在内循环中。

【讨论】:

  • 我接受这一点是因为我认为 Raymond 在他建议(对 OP 的评论)应该将其重新定义为 MySQL 问题而不是 Python 问题时走在正确的轨道上。我认为尝试在 Python 中完成所有这些操作可能是一个错误。
【解决方案2】:

假设您的列表看起来像这样

LISTID LISTITEM
1      1
1      2
1      3
2      2
2      4
2      5

并且列表A是例如。 [1,2],你可以在 SQL 中这样做:

SELECT LISTID, COUNT(*)
FROM T
WHERE LISTITEM IN (1,2)
GROUP BY LISTID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多