【问题标题】:php : speed up levensthein comparing, 10k + recordsphp : 加快 levensthein 比较,10k + 记录
【发布时间】:2015-05-06 14:56:00
【问题描述】:

在我的 MySQL 表中,我有唯一的字段名称。然而,该领域的内容收集在不同的地方。因此,由于拼写错误,我可能有 2 条名称非常相似的记录,而不是第二条记录。

现在我想找到那些与另一个条目非常相似的条目。为此,我遍历所有记录,并通过再次遍历所有记录将名称与其他条目进行比较。问题是有超过 15k 条记录需要太多时间。有没有办法更快地做到这一点?

这是我的代码:

for($x=0;$x<count($serie1);$x++)
    {
    for($y=0;$y<count($serie2);$y++)
        {
        $sim=levenshtein($serie1[$x]['naam'],$serie2[$y]['naam']);
        if($sim==1)
            print("{$A[$x]['naam']} --> {$B[$y]['naam']} = {$sim}<br>");
        }
     }
 }

【问题讨论】:

  • 如果您避免在每次迭代中计算元素并且将元素的数量存储在变量中,则可能会感觉到一些改进
  • 数据库中的列类型是什么?

标签: php mysql performance


【解决方案1】:

序言:这样的任务总是很耗时,而且总会有一些配对漏掉。 不过,有一些想法:

1。实际上,算法可以(有点)改进

假设$series1$series2 具有相同顺序的相同值,您不需要每次都在内部循环中循环整个第二个数组。在这个用例中,您只需要评估每个值对一次 - levenshtein('a', 'b') 就足够了,您也不需要 levenshtein('b', 'a')(您也不需要 levenstein('a', 'a')

在这些假设下,您可以这样编写函数:

for($x=0;$x<count($serie1);$x++)
{
   for($y=$x+1;$y<count($serie2);$y++) // <-- $y doesn't need to start at 0
    {
      $sim=levenshtein($serie1[$x]['naam'],$serie2[$y]['naam']);
      if($sim==1)
        print("{$A[$x]['naam']} --> {$B[$y]['naam']} = {$sim}<br>");
    }
 }

2。也许 MySQL 更快

网络中有 levenshtein() 实现作为 MySQL 函数的示例。一个关于 SO 的例子在这里:How to add levenshtein function in mysql?

如果您对复杂的(ish)SQL 感到满意,您可以将繁重的工作委托给 MySQL,并且至少获得一点性能,因为您不会将整个 16k 行提取到 PHP 运行时中。

3。不要一次做所有事情/保存你的结果

当然,您必须为每条记录运行一次该函数,但在初始运行之后,您只需检查自上次运行以来的新条目。安排一个每天/每周/每月一次的 chronjob.. 检查所有新记录。您需要在表中添加一个 inserted_at 列,并且仍需要将新名称与其他所有名称条目进行比较。

3.5 做一些关于Insert的工作

a) 如果等待是可以接受的,请在应该插入新记录后进行检查,以便将其写入日志或直接反馈给用户。 (切线:这对于像http://gearman.org/ 这样的异步任务队列来说可能是一个很好的用例 -> 在后台启动一个新进程进行检查,立即返回插入成功消息)

b) PHP 还有两个函数可以帮助搜索几乎相似的字符串:metaphone()soundex()。这些函数生成抽象散列,代表字符串在说出时的发音。您可以在每次插入时生成(一个或两个)这些哈希值,将它们作为单独的字段存储在表中,并使用简单的 SQL 函数来查找具有相似哈希值的记录

【讨论】:

    【解决方案2】:

    levenshtein 的问题在于它只比较字符串 a 和字符串 b。有一次,我构建了一个拼写校正器,它将所有字符串 a 放入一个大树中,并起到字典的作用。然后它将查找该字典中的任何字符串 b ,找到所有最近匹配的单词。我首先在 Fortran (!) 中完成,然后在 Pascal 中完成。在更现代的语言中这将是最简单的,但我怀疑 php 不会让它变得容易。 Look here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2018-11-18
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 2018-06-07
      相关资源
      最近更新 更多