簡體   English   中英

在20mb平面文件數據庫(PHP)中搜索整個單詞的最快方法

[英]Fastest way to search for whole words in 20mb flat file database (PHP)

我有20MB的平面文件數據庫,大約有500k行,僅允許[a-z0-9-]字符,平均每行7個字,沒有空行或重復行:

平面文件數據庫:

put-returns-between-paragraphs
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces

我只搜索whole words only然后從該數據庫中提取first 10k results

到目前為止,如果在數據庫的前20k行中找到了10k個匹配項,此代碼就可以正常工作,但是如果單詞很少,則腳本必須搜索所有500k行,這慢了10倍。

設定:

$cats = file("cats.txt", FILE_IGNORE_NEW_LINES);
$search = "end";
$limit = 10000;

搜索:

foreach($cats as $cat) {
    if(preg_match("/\b$search\b/", $cat)) {
        $cats_found[] = $cat;
        if(isset($cats_found[$limit])) break;
    }
}

我的PHP技能和知識有限,我不能也不知道如何使用sql,所以這是我能做到的最好的方法,但是我需要一些建議:

  • 這是正確的代碼嗎,foreach和preg_match是問題?
  • 我應該將大文件拆分為小文件嗎?
  • 最后,sql會更快嗎? (未來的選擇)

感謝您閱讀本文,對不起,英語不好,這是我的第三語言。

如果大多數行不包含搜索到的單詞,則可以減少執行preg_match()頻率,如下所示:

foreach ($lines as $line) {
    // fast prefilter...
    if (strpos($line, $word) === false) {
        continue;
    }
    // ... then proper search if the line passed the prefilter
    if (preg_match("/\b{$word}\b/", $line)) {
        // found
    }
}

不過,這需要在實際情況下進行基准測試。

盡管您可能會用盡內存,但是這將適合您逐行閱讀:

(可能需要調整php.ini的memory_limit和max_execution_time或通過cli運行)

$rFile = fopen( 'inputfile.txt', 'r' );
$iLineNumber = 0;
$sSearch = '123';
$iLimit  = 5000;
while( !feof( $rFile ) )
{
    if( $iLineNumber > $iLimit )
    {
        break;
    }
    $sLine = fgets( $rFile );
    if( preg_match("/\b$sSearch\b/", $sLine, $aMatches ) ) 
    {
        $aCats[] = $aMatches[ 0 ];
    }
    ++$iLineNumber;
}
var_dump( $aCats );

我的建議是將文件重新格式化為sql導入並使用數據庫。 平面文件搜索明顯較慢。

文件內:

put-returns-between-paragraphs
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces
put-returns-between-paragraphs
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces
put-returns-between-paragraphs
123
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces
put-returns-between-paragraphs
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces
123
put-returns-between-paragraphs
for-linebreak-add-2-spaces-at-end
indent-code-by-4-spaces-indent-code-by-4-spaces

輸出:

array(2) {
  [0]=>
  string(3) "123"
  [1]=>
  string(3) "123"
}

它從匹配中包裝了一個附加數組,所以我們必須使用[0]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM