Збираючи величезний файл (80 Гб) будь-яким способом прискорити його?


113
 grep -i -A 5 -B 5 'db_pd.Clients'  eightygigsfile.sql

Це працює протягом години на досить потужному сервері Linux, який інакше не перевантажений. Будь-яка альтернатива grep? Що-небудь про мій синтаксис, який можна вдосконалити, (egrep, fgrep краще?)

Файл насправді знаходиться в каталозі, який спільно використовується з монтом на інший сервер, але власне дисковий простір є локальним, тому не повинно бути ніяких змін?

греп захоплює до 93% процесора


8
Залежно від вашої локальної локації, -iкомутатор може сповільнити процес, спробувати без -iабо з LC_ALL=C grep .... Крім того, якщо ви шукаєте лише фіксовану струну, використовуйте grep -F.
Тор

5
Як згадував @dogbane, використання змінної LC_ALL = C разом із fgrep може пришвидшити ваш пошук. Я провів кілька тестувань і зміг досягти 1400% підвищення продуктивності і написав детальну статтю, чому це в моєму прискоренні
греп-

Мені цікаво - який файл розміром 80 Гб? Я хотів би подумати, що коли файл набуває такого великого розміру, може бути краща стратегія зберігання (наприклад, обертові файли журналів або класифікація ієрархічно в різні файли та папки). Крім того, якщо зміни відбуваються лише в певних місцях файлу (наприклад, в кінці), тоді просто збережіть деякі результати грепування з попереднього розділу, який не змінюється, і замість того, щоб схоплювати оригінальний файл, намалюйте збережений файл результатів.
Шрідхар Сарнобат

Я влаштувався на github.com/google/codesearch - і індексація, і пошук блискавично (написано Go). cindex .проіндексуйте поточну папку csearch db_pd.Clients.
ccpizza

1
Якщо ваш файл було індексовано чи відсортовано, це може бути значно швидше. Пошук у кожному рядку є O (n) за визначенням, тоді як відсортований файл можна шукати, розділяючи його - у цей момент ви б хотіли говорити за секунду, щоб шукати 80gb (отже, чому індексована база даних 80gb не займає часу взагалі для простого SELECT, тоді як ваш греп займає ... ну, скільки часу потрібно).
Чарльз Даффі

Відповіді:


148

Ось кілька варіантів:

1) Поставте команду grep, LC_ALL=Cщоб використовувати локаль C замість UTF-8.

2) Використовуйте, fgrepоскільки ви шукаєте фіксовану рядок, а не регулярний вираз.

3) Видаліть -iопцію, якщо вона вам не потрібна.

Отже ваша команда стає:

LC_ALL=C fgrep -A 5 -B 5 'db_pd.Clients' eightygigsfile.sql

Це також буде швидше, якщо ви скопіюєте файл на диск RAM.


5
це було набагато швидше на порядок подяки. До речі, я додав -n, щоб отримати номери рядків. Також можливо -m для виходу після матчу
zzapper

5
Дякую, спасибі @dogbane чудовий рада! Це привело мене вниз по дослідницькому тунелю, щоб з’ясувати, чому LC_ALL = C прискорює греп, і це було дуже просвічуючим досвідом!
ЯківN

7
Деяким людям (не мені) подобається grep -Fбільше, ніжfgrep
Вальтер Трос

2
Я розумію, що LANG=C(замість LC_ALL=C) достатньо і простіше набрати.
Уолтер Трос

2
@ Адріан fgrep- це ще один спосіб писати grep -F, як man fgrepвам скажуть. Деякі версії manтакож говорять про те, що перший є застарілим для другого, але коротша форма занадто зручна для смерті.
Вальтер Трос

36

Якщо у вас багатоядерний процесор, я б дуже рекомендував GNU паралельно . Для паралельного використання великого файлу:

< eightygigsfile.sql parallel --pipe grep -i -C 5 'db_pd.Clients'

Залежно від ваших дисків та процесорів читання великих блоків може бути швидше:

< eightygigsfile.sql parallel --pipe --block 10M grep -i -C 5 'db_pd.Clients'

З вас не зовсім зрозуміло питання, але інші варіанти grepвключення:

  • Скидання -iпрапора.
  • Використання -Fпрапора для фіксованого рядка
  • Відключення NLS с LANG=C
  • Встановлення максимальної кількості збігів із -mпрапором.

2
Якщо це фактичний файл, використовуйте --pipepartзамість --pipe. Це набагато швидше.
Оле Танге

Цей шаблон використання не підтримує, включаючи простір, нам потрібно використовувати так: паралельний --pipe --block 10M "/ usr / bin / grep -F -C5 -e" Догляд за тваринами та домашні тварини "
zw963

Що означає <символ, що передує паралельній команді?
elcortegano

1
@elcortegano: Ось що називається перенаправленням вводу / виводу . В основному, він читає вхід із наступного імені файлу. Схожий на, cat file.sql | parallel ...але уникає UUOC . Паралельно GNU також має можливість зчитувати вхід з файлу за допомогою parallel ... :::: file.sql. HTH.
Стів

10

Деякі дрібниці:

  • Усуньте варіант -i, якщо можете, нечутливий випадок буває досить повільним.

  • Замініть .на\.

    Єдиною точкою є символ регулярного вираження, який відповідає будь-якому символу, який також є повільним


3

Дві лінії нападу:

  • ти впевнений, що тобі потрібен -i, чи ти не маєш можливості позбутися від нього?
  • У вас є більше ядер, щоб грати? grepє однопотоковою, тому, можливо, ви хочете запустити їх більше при різних зсувах.

1
< eightygigsfile.sql parallel -k -j120% -n10 -m grep -F -i -C 5 'db_pd.Clients'  

Якщо вам потрібно шукати кілька рядків, grep -f strings.txt економить тону часу. Сказане - це переклад того, що я зараз тестую. Значення параметрів -j та -n, здавалося, найкраще працює у випадку мого використання. Гріп -F також зробив велику зміну.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.