我有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,所以这是我能做到的最好的,但我需要一些建议:
感谢您阅读本文并对不良英语感到抱歉,这是我的第三语言。
答案 0 :(得分:2)
如果大多数的行不包含搜索到的字词,则可以较少执行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
}
}
但是,它需要在实际情况下进行基准测试。
答案 1 :(得分:1)
这可能会让你逐行阅读,虽然你的内存可能会耗尽:
(可能需要调整你的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 import 并使用数据库。平面文件搜索速度明显变慢。
INFILE:
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]