2017-07-06 79 views
0

我遇到了优化我在PHP中创建的搜索的问题,此搜索是一次性使用,因此灵活性并不重要。优化跨多个文档的句子搜索

我有一个阵列的句子,如:

$arr = [ 
    'potato', 
    'hi my name is Ivan' 
    .. 
]; 

数组包含1K左右的句子。

而我有一个200 GB的文件的硬盘。

我需要搜索所有文件,并查看这些语句是否存在于这些文件中,如果是,则打印出特定格式的路径,校验和等。

我现在面临的问题是搜索时间,做这样的事情,这似乎效率不高时:

$objections = []; 
foreach ($files as $file) { 

    if (!in_array($file->getExtension(), $allowedExt)) 
     continue; 

    $txt = file_get_contents($file); 

    foreach ($words as $word) { 
     if (stripos($txt, $word) !== false || 
      stripos($file->getFilename(), $word) !== false 
      ) { 
      $file->c_md5 = getCMD5($file); 
      $objections[] = $file; 
     } 
    } 
} 

搜索它自走年龄1H +,我上了一个新的MacBook采用最新酷睿i7 。随着PHP内存等最大。

这是不相关的单词数组匹配,所以我想知道是否有一些更聪明的方式来执行搜索,而不是循环文件循环内的单词。 OR的长REGEX字符串会更快吗?

还是有第三种方式,它是很快。

+0

我不不知道一个大的正则表达式是否会更快,但是如果你对如何做一个(你似乎)有一个想法,只需尝试一下并进行基准测试。有了这些数据,它可能会非常慢,无论如何。 –

回答

0

绝对答案是一个正则表达式。你应该把它分割成三个阶段:

  1. 转换你的句子的名单成一个大的正则表达式或正则表达式的列表,在一个循环中运行。您可以将空格转换为空格\s并使搜索非贪婪/regex/U

  2. 迭代文件并删除换行结尾的空行。以防万一句子分散在多行。

  3. 使用preg_match来确定句子是否在文件中。如果您决定使用多个正则表达式,则可以在循环中执行此操作。

+1

我认为,如果你使用正则表达式,你应该有一个大的正则表达式,否则你基本上只是实现了原始代码已经做的更慢的方式。正则表达式对简单的字符串比较效率不高。 (但如果你不需要遍历每个文件中的每个句子,它会变得更有效率)。 –

+0

@MagnusEriksson我同意,一个大的正则表达式应该会更好。 –

+0

我会测试一个正则表达式和基准 –

0

正则表达式可以为你节省很少或没有。

你可以跳出命中的循环。

Foreach{ 
    If(hit){ 
     Break; 
    } 
} 

哪一个可以节省寻找其余的。因此,如果你在第二次迭代中进行操作,则不必再对该文档进行998次迭代。

您总是会遇到的问题是文档的打开,毫无疑问,您的大部分性能都会丢失。

如果这是需要多次执行的操作,则可能需要考虑将您的所有文件编入索引到设计用于全文搜索的数据库中,例如ElasticSearch。在你的数据库中,你可以简单地保留对下一步操作的物理文件的引用。 所有这些文件的初始加载和索引将承认需要一些大的资源和时间。但一旦完成您的搜索将是真的快。

+0

啊,是的,我忘了补充一点,匹配是很少的,但是是的,应该def保存一段时间 –

+0

然后我会认真考虑实现像上面提到的ElasticSearch这样的数据库。你已经加载了所有的文件内容,抛出它的intiba数据库将是微不足道的,然后搜索将需要一些功能。 ElasticSearch的文档非常棒。 – Doug

+0

即使MySQL上的全文搜索可能会更快。 –

0

您可以使用exec

创建一个test.php的文件,并尝试这个代码

<?php 
    exec('grep '.escapeshellarg('end').' '."./test.php",$result);    
    print_r($result); 
    /* serach for some sentences 
    * keep seraching 
    * end of comment */ 
    ?> 

Ofcourse,你将不得不首先测试它的性能则根据需要自定义