Что-нибудь быстрее, чем grep?

11188
Jeffrey L. Roberts

Я ищу инструмент, который будет быстрее, чем grep, может быть многопоточный grep, или что-то подобное ... Я смотрел на кучу индексаторов, но я не продал, что мне нужен индекс ...

У меня есть около 100 миллионов текстовых файлов, которые мне нужно grep для точных совпадений строк, при нахождении совпадения строк мне нужно имя файла, где совпадение было найдено.

ie: grep -r 'exact match' > filepaths.log 

Это около 4 ТБ данных, и я начал свой первый поиск 6 дней назад, и grep все еще работает. У меня есть еще дюжина поисков, и я не могу ждать 2 месяца, чтобы получить все эти имена файлов =]

Я рассмотрел следующее, однако, я не думаю, что мне нужны все навороты, с которыми идут эти индексаторы, мне просто нужно имя файла, где произошло совпадение ...

  • DTSearch
  • Терьер
  • Lucene
  • Xapian
  • отдача
  • сфинкс

и после нескольких часов чтения обо всех этих двигателях у меня кружится голова, и мне бы хотелось, чтобы у меня был многопоточный grep lol, любые идеи и / или предложения очень ценятся!

PS: я использую CentOS 6.5

РЕДАКТИРОВАТЬ: поиск многопоточных grep возвращает несколько элементов, мой вопрос, является ли многопоточный grep лучшим вариантом для того, что я делаю?

РЕДАКТИРОВАТЬ 2: После некоторой настройки, это то, что я придумал, и он идет намного быстрее, чем обычный grep, я все еще хотел бы, чтобы он был быстрее, хотя ... Я смотрю, как мой диск ждет, и он еще не собирается Я могу сделать еще несколько настроек, и def по-прежнему заинтересован в любых предложениях =]

find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string' 
1
Таким образом, вы действительно планируете искать более одной строки, верно? Многопоточность не поможет, потому что вы ограничены пропускной способностью диска и (что более важно) ищите производительность. Daniel B 9 лет назад 0
да, диски являются определением узкого места здесь Jeffrey L. Roberts 9 лет назад 0
"100 миллионов текстовых файлов" ... правда? и подход на самом деле все зависит от того, является ли это единовременной вещью или действительно ли данные должны быть проиндексированы для будущего использования. Tyson 9 лет назад 0
да ... правда. LOL =] Это более или менее единовременно для около 2 десятков поисков в общей сложности Jeffrey L. Roberts 9 лет назад 0

2 ответа на вопрос

9
Kenster

grepсвязан с вводом / выводом, что означает, что его скорость определяется скоростью чтения файлов, которые он ищет. Несколько параллельных поисков могут конкурировать друг с другом за дисковый ввод-вывод, поэтому вы можете не заметить значительного ускорения.

Если вам просто нужны совпадающие имена файлов, а не фактические совпадения, найденные в файлах, тогда вы должны запустить grep с -lфлагом. Этот флаг заставляет grep просто печатать имена файлов, которые совпадают, а не печатать совпадающие строки. Значение здесь в том, что он позволяет grep прекращать поиск файла после того, как он найдет совпадение, что может уменьшить объем работы, которую должен выполнить grep.

Если вы ищете фиксированные строки, а не регулярные выражения, то вы можете попробовать использовать fgrepвместо grep. Fgrep - это вариант grep, который ищет фиксированные строки, и поиск фиксированных строк быстрее, чем поиск по регулярному выражению. Вы можете увидеть или не увидеть каких-либо улучшений от этого, потому что современные версии grep, вероятно, достаточно умны, чтобы в любом случае оптимизировать поиск по фиксированным строкам.

Если вы хотите попробовать запустить несколько запросов параллельно, вы можете сделать это с помощью утилит оболочки. Одним из способов было бы создать список имен файлов, разделить его на части и запустить grep отдельно для каждого списка:

find /path/to/files -type f -print | split -l 10000000 list. for file in list.*; do grep -f $ -l 'some text' > $.out & done wait cat $*.out > filepaths.log rm list.* 

Он используется findдля поиска файлов, разбивает список имен файлов на группы по десять миллионов и параллельно запускает grep для каждой группы. Выходные данные greps все соединены вместе в конце. Это должно работать для файлов с типичными именами, но не будет работать с файлами, в которых, например, есть новые строки.

Другой подход использует xargs. Во-первых, вам нужно написать простой скрипт оболочки, который запускает grep в фоновом режиме:

#!/bin/bash grep -l 'search text' "$@" >> grep.$$.out & 

Это запустит grep в списке файлов, указанных в качестве аргументов скрипта, записав результат в файл с именем PID процесса. Процесс grep работает в фоновом режиме.

Тогда вы запустите скрипт так:

find /path/to/files -type f -print0 | xargs -0 -r /my/grep/script [ wait for those to finish ] cat grep.*.out > filepaths.log rm grep.*.out 

В этом случае xargsбудет объединять имена файлов в группы и запускать сценарий один раз для каждой группы. Скрипт запускает экземпляр grep один раз для каждой группы. После завершения всех экземпляров grep вы можете объединить их результаты. К сожалению, я не мог придумать умного способа автоматического ожидания завершения экземпляров grep, поэтому вам, возможно, придется сделать это вручную.

Если вам не нужно регулярное выражение, одним из преимуществ fgrep является то, что вам не нужно беспокоиться о экранировании зарезервированных символов, например, `fgrep '..'` вместо `grep '\. \.'`. thdoan 8 лет назад 0
0
Kristian

Похоже, вам нужен скрипт или небольшая программа, которая будет запускать несколько экземпляров (то есть 8 x grep могут быть запущены параллельно на современном i7 с 4 ядрами / 8 нитями) из grep и объединять или объединять вывод, больше, чем вам нужен более быстрый grep ,

Как сделать такой сценарий - это совсем другой вопрос, но я бы так решил на вашу проблему.

Если файлы находятся на нескольких дисках, возможно, но это связано с IO, а не с процессором. Christophe Roussy 6 лет назад 0

Похожие вопросы