2017-07-06 26 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,你將不得不首先測試它的性能則根據需要自定義