我有一个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导入并使用数据库。平面文件搜索速度明显较慢。
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]