在 MySQL 数据库中进行 REGEXP 查找和替换的最快方法是啥?

Posted

技术标签:

【中文标题】在 MySQL 数据库中进行 REGEXP 查找和替换的最快方法是啥?【英文标题】:What is the fastest way to do a REGEXP find and Replace in MySQL database?在 MySQL 数据库中进行 REGEXP 查找和替换的最快方法是什么? 【发布时间】:2015-10-13 03:25:22 【问题描述】:

我有一个包含 700,000 个条目的表,我需要检查每个条目中的 1,000,000 个单词,然后将找到的单词从 hello 替换为 #~hello~#。单词可以在一个条目中出现多次,并且需要全部替换。我在 php 中尝试过这个,估计完成代码的时间大约是 362 天。我刚刚修改了代码以在 mysql 中使用 LIKE,这样我就没有针对所有 700,000 个条目检查 1,000,000 个单词中的每一个,但估计完成时间仍然是 29 天。这似乎真的很高。

使事情更复杂的词可能是多个词。例如,如果单词是hello world,则程序应替换为#~hello world~#

我错过了什么?

代码如下所示:

$query = "SELECT word_id, word_name, FROM words ORDER BY char_length(word_name) DESC";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result))
  $words[$i] = new wordObj($row['word_id'], $row['word_name']);


Foreach($words as $word)
  $query = "SELECT id, entry FROM entries WHERE entry LIKE '%".$word."%'";
  $result = mysqli_query($con, $query);
  if ($result) 
    if ($result->num_rows != 0) 
      while($row = mysqli_fetch_array($result))
        $entry[$i] = new meatObj($row['id'], $row['entry']);
        $i++;
      
    else
      $entry = '';
    
  else
    $entry ='';
  
  foreach($entryArray as $entry)
    check entry for all words and replace
  

【问题讨论】:

你能告诉我们查询吗? 10 倍的改进是巨大的,你不应该打折扣。 已编辑问题,感谢您的帮助! 你会只做一次还是经常做? 在循环中运行查询总是比在循环中解析数组要慢 【参考方案1】:

最简单的解决方案是将所有需要替换的单词存储在哈希表中。然后在每个条目上,我们打破所有单词并检查哈希表。

// HOW DOES TAKE 29 DAYS TO EXECUTE?
// Create a hash table to store all the words
$hash = array();

$query = "SELECT word_id, word_name, FROM words ORDER BY char_length(word_name) DESC";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result))
    $hash[strtolower($row['word_name'])] = true;




// DO SOME QUERY HERE
// .....

while($row = mysqli_fetch_array($result)) 
    $delimiter = "/([ \.,\"'!\?\-_;])/";
    $tokens = preg_split($delimiter, $row['entry'], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));

    // replace the text
    $final = "";
    foreach($tokens as $token) 
        if (isset($hash[strtolower($token)])) 
            $final .= "#~" $token . "~#";
         else 
            $final .= $token;
        
    

    // UPDATE NEW ENTRY HERE
    // .......

【讨论】:

这很好,如果它确实比正则表达式更快,它可能会加快搜索和替换速度。但是,瓶颈似乎是每个word 大约需要 2 秒的查询,如果仅查询需要 2,000,000 秒 = 23 天... @alutz33,你的解决方案不是也需要加载单词吗?那么在您的解决方案中加载单词也需要 23 天吗? 我编辑了帖子,以便您查看word 数组是如何生成的。我只是在创建一个对象数组。这个过程总共需要大约 30 秒。 @alutz33,创建哈希表需要 29 天,而您的解决方案需要 30 秒,而代码几乎执行相同的查询? 因为第一个查询只是将单词转储到对象数组中,而第二个查询正在查看 700,00 个条目,其中每个条目可以是从句子到特定单词的多个段落的任何地方。我必须对 1,000,000 个单词中的每一个进行查询,每个查询大约需要 2 秒。

以上是关于在 MySQL 数据库中进行 REGEXP 查找和替换的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

《零基础》MySQL 正则表达式(二十一)

如何使用 REGEXP MySQL 函数查找超过 2 个点的电子邮件?

MySQL中REGEXP正则表达式使用大全

mysql模糊查询 like/REGEXP

go语言中regexp包中的函数和方法

MySQL之正则表达式(REGEXP)