Самый быстрый способ поиска целых слов в базе данных с плоскими файлами 20 МБ (PHP)

У меня есть база данных размером 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, так что это лучшее, что я могу сделать, но мне нужны некоторые советы:

  • Это правильный код для этого, foreach и preg_match являются проблемой?
  • Должен ли я разбить большой файл на меньшие, если да, то какого размера?
  • И, наконец, будет ли sql быстрее и насколько? (Вариант на будущее)

Спасибо за чтение и извините за плохой английский, это мой третий язык.

0

Решение

Если самый из строк не содержат искомого слова, вы можете выполнить 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
}
}

Тем не менее, это требует сравнительного анализа в практической ситуации.

2

Другие решения

Это будет работать для вас, читая построчно, хотя вам может не хватить памяти:

(может потребоваться настроить 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]

1

По вопросам рекламы [email protected]