Збираючи величезний файл (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.