java mysql - 如何快速执行许多复杂的计算?

Posted

技术标签:

【中文标题】java mysql - 如何快速执行许多复杂的计算?【英文标题】:java mysql - how to perform many complex calculations fast? 【发布时间】:2013-01-12 02:09:15 【问题描述】:

我有以下问题:

我正在寻找相似之处。因此,我有一个包含 200000 个条目的大源表和包含 10000 个条目的第二个表。现在我正在为每个表检索一个条目集,并将源表中的每一行与 java 中第二个表中的每一行进行比较(我正在使用一些 NeedleMan Gotoh 算法和类似的更复杂的算法)。这意味着要进行 10 亿次比较,这实在是太多太慢了……

目标是具有所有相似性的表(来自源表的 id、来自第二个表的 id 和相似性值)或至少类似于每个条目的最佳匹配(或最佳 x 匹配)...

谁能给我一些建议,让我在“正常”时间进行此类计算?

编辑

主表

---+------+-------------+---------+-------+
id | name | address     | country | plz   | ...
---+------+-------------+---------+-------+
20 | Sony | Main Str. 1 | US      | 10000 |
---+------+-------------+---------+-------+

第二张桌子

---+------+-------------+---------+-------+
id | name | address     | country | plz   | ...
---+------+-------------+---------+-------+
30 | Soni | MainStr. 1  | US      | 10000 |
---+------+-------------+---------+-------+

目标(相似度表):

---+---------------+--------------+-----------+
id | id_source_tbl | id_second_tbl| similarity|
---+---------------+--------------+-----------+
1  | 20            | 30           | 0.99      |
---+---------------+--------------+-----------+

simil_value 是一个值,表示源表中的公司与第二个表中的公司相同的可能性有多大

结果表明,这两行代表同一家公司...这两个条目只是因为小错别字而不同...(0.99 是相似度并且非常高 => 公司是相同的) 相似度是用 needleman wunsch gotoh 算法计算的(比较 char 和 char 并考虑在字符串中的位置等等......拼写错误应该导致高相似度值)

【问题讨论】:

请发布您的表格结构 你不能让 mysql 为你“预计算”一些数据,而不是用 Java 做所有事情吗? 其实一开始,这不是问题... 20亿次计算,即使每个人在1ms内完成,也需要大约23天...所以首先我得想办法为了避免其中一些计算...我还没有这个想法,但是... @prom85 我们需要有关计算的更多信息。我建议在问题中的表格中添加一些示例数据集,并举例说明结果应该是什么样的 无论如何,这些都是二次或三次算法,在任何两对之间,其中 N 是每个字符串的长度,并且您通过将 200,000 个项目与 100,000 个项目进行比较来添加另一个 O(N2)其他项目。所以性能将是 O(N4) 或 O(N**5)。你在这里给自己设置了一个相当不可行的问题。 【参考方案1】:

这听起来像是一个令人尴尬的并行问题,因此作为第一步,您可以在多个内核和机器上进行分析。

【讨论】:

实际上,这对我来说别无选择......我无法使用硬件......我只有四核和一台机器...... 所以,请务必使用所有四个核心。 如今,您无需真正拥有计算机。云可以以一定的价格为您提供几乎无限的计算资源。如果您想快速完成工作,请获取 1000 个亚马逊实例并前往城镇。 23 天(我认为是您的估计)变成了 30 分钟左右。【参考方案2】:

允许 MySQL 执行数据选择通常比检索大量数据集然后使用您自己的算法过滤它更有意义。听起来您所做的只是一个相当简单的连接操作,例如:

SELECT source_id_column, second_id_column, similarity_column
FROM source_table, second_table
WHERE source_table.similarity_column = second_table.similarity;

【讨论】:

相似度列不存在...必须先计算值...然后我需要最佳匹配... @prom85 你能具体点吗? MySQL 仍然有可能做到这一切。正在计算什么,“最佳匹配”是什么意思 - 平等?数字是否在范围内? @prom85 也许发布一个示例数据集,结果应该是什么样子 @prom85 您已经定义了表格,但不是数据示例以及您正在执行的计算。在不知道这些信息的情况下很难提出解决方案。【参考方案3】:

在 SQL 中,您可以将其表示为:

选择t1.id作为id1,t2.id作为id2, calculate_similarity(t1.name, t2.name) 作为相似度 从 t1 交叉连接 t2

现在,您要将相似度表定义为:

create table similarity (
    SimilarityID int not null auto_increment,
    id1 int,
    id2 int,
    similarity float
)

然后插入如下:

insert into similarity(id1, id2, similarity)
    select t1.id as id1, t2.id as id2,
           calculate_similarity(t1.name, t2.name) as similarity
    from t1 cross join
         t2

SQL 引擎应该并行执行交叉连接以及相似度计算。也许你有办法限制查询,例如要求公司处于相同的状态或以相同的字母开头。

【讨论】:

这意味着我必须编写一个 sql 过程,不是吗?我不能以某种方式直接在 sql 查询中使用 java 函数,是吗?【参考方案4】:

其实问题是我自己做的……

我的解决方案如下: 1) 不要重用连接,总是用相应的 ResultSet 关闭它们 2) 使用交易 3) 将工作拆分为线程 4)如果你和我一样,有单行的结果(一个条目的所有相似性)并且想在这个子结果上计算一些东西(就像在我的情况下,对于我想计算排名的所有相似性),在 java 中执行此操作并使用子结果!!!!而不是之后在 mysql 中执行此操作

对我来说结果是大约 1 天的计算时间而不是 3 周...

感谢您的帮助

【讨论】:

以上是关于java mysql - 如何快速执行许多复杂的计算?的主要内容,如果未能解决你的问题,请参考以下文章

Java——final关键字

如何快速学习 Java RMI [关闭]

java中的编译时常量与运行时常量

如何在 laravel 中执行复杂的 mysql 查询

Java 之SpringData Redis快速入门 以及( Redis快速入门安装和使用)

Java 之SpringData Redis快速入门 以及( Redis快速入门安装和使用)