У меня есть база данных размером 20 МБ с 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
из этой базы данных
Пока что этот код работает нормально, если найдены совпадения в 10 000, скажем, в первых 20 000 строках БД, но если слово встречается редко, скрипт должен искать все 500 000 строк, а это в 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, так что это лучшее, что я могу сделать, но мне нужны некоторые советы:
Спасибо за чтение и извините за плохой английский, это мой третий язык.
Если самый из строк не содержат искомого слова, вы можете выполнить 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]