속도를 높이기 위해 대용량 파일 (80GB)을 저장 하시겠습니까?


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

이것은 과부하가 걸리지 않는 상당히 강력한 리눅스 서버에서 한 시간 동안 실행되었습니다. grep에 대한 대안이 있습니까? 개선 할 수있는 내 구문에 대한 모든 것, (egrep, fgrep 더 나은가?)

파일은 실제로 다른 서버에 마운트와 공유되는 디렉토리에 있지만 실제 디스크 공간은 로컬이므로 차이가 없습니다.

grep은 최대 93 % CPU를 차지합니다.


8
로케일에 따라 -i스위치가 프로세스 속도를 늦추 -i거나 LC_ALL=C grep .... 또한 고정 문자열에 대해서만 grepping하는 경우 grep -F.
토르

5
@dogbane이 언급했듯이 fgrep 과 함께 LC_ALL = C 변수를 사용하면 검색 속도를 높일 수 있습니다. 몇 가지 테스트를 수행하여 1400 %의 성능 향상 을 달성 할 수 있었고 이것이 내 속도 향상 grep 게시물에 있는 이유에 대한 자세한 기사를 작성했습니다
JacobN

궁금합니다. 80GB의 파일 크기는 무엇입니까? 파일이 그렇게 커지면 더 나은 저장 전략이있을 수 있다고 생각하고 싶습니다 (예 : 로그 파일을 회전하거나 다른 파일 및 폴더로 계층 적으로 분류). 또한 변경 사항이 파일의 특정 위치 (예 : 끝 부분)에서만 발생하는 경우 변경되지 않는 이전 섹션의 grep 결과를 저장하고 원본 파일을 grepping하는 대신 저장된 결과 파일을 grep합니다.
Sridhar Sarnobat

나는 github.com/google/codesearch에 정착했습니다. 색인과 검색 모두 매우 빠릅니다 (Go로 작성). cindex .현재 폴더를 인덱싱하려면 csearch db_pd.Clients.
ccpizza 2017-10-28

1
파일이 인덱싱되거나 정렬 된 경우 훨씬 더 빠르게 만들 수 있습니다 . 모든 줄을 검색하는 것은 정의에 따라 O (n)이지만 정렬 된 파일은 이등분하여 검색 할 수 있습니다.이 시점에서 80GB를 검색하는 데 1 초 안에 이야기해야합니다 (따라서 80GB 색인화 된 데이터베이스는 시간이 전혀 걸리지 않습니다. 간단한 SELECT의 경우 grep이 걸리는 반면 ... 소요되는 한).
Charles Duffy

답변:


148

다음은 몇 가지 옵션입니다.

1) LC_ALL=CUTF-8 대신 C 로켈을 사용하려면 grep 명령을 접두사로 지정하십시오 .

2) fgrep정규 표현식이 아닌 고정 문자열을 검색하기 때문에 사용하십시오 .

3) -i필요하지 않은 경우 옵션을 제거합니다 .

따라서 명령은 다음과 같습니다.

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

파일을 RAM 디스크에 복사하면 더 빠릅니다.


5
그 덕분에 훨씬 더 빨라졌습니다. BTW 나는 줄 번호를 얻기 위해 -n을 추가했습니다. 또한 경기 후 종료 할 -m
zzapper

5
@dogbane 훌륭한 팁에 감사드립니다! 이로 인해 LC_ALL = C가 grep 속도를 높이는 이유 를 알아보기 위해 연구 터널을 내려 갔고 매우 깨달은 경험이었습니다!
JacobN 2013-08-23

7
같은 어떤 사람들은 (내가 아니라) grep -F이상fgrep
월터 Tross

2
내 이해는 LANG=C(대신 LC_ALL=C) 충분하고 입력하기가 더 쉽습니다.
Walter Tross 2014-06-18

2
@Adrian는 fgrep쓰기에 또 다른 방법 grep -F으로, man fgrep당신을 말할 것이다. 일부 버전 man에서는 전자가 후자에 대해 더 이상 사용되지 않는다고 말하지만 더 짧은 형식은 죽기에는 너무 편리합니다.
Walter Tross 2016 년

36

멀티 코어 CPU가 있다면 정말 GNU parallel을 권장 합니다 . 큰 파일을 병렬로 grep하려면 다음을 수행하십시오.

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

디스크 및 CPU에 따라 더 큰 블록을 읽는 것이 더 빠를 수 있습니다.

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

질문에서 완전히 명확하지는 않지만 다음과 같은 다른 옵션이 grep있습니다.

  • -i깃발을 떨어 뜨리는 것 .
  • -F고정 문자열에 플래그 사용
  • NLS 비활성화 LANG=C
  • -m플래그 와 일치하는 최대 수를 설정합니다 .

2
이 실제 파일 인 경우, 사용 --pipepart대신에 --pipe. 훨씬 빠릅니다.
Ole Tange

이 사용법은 공간을 포함하지 않습니다. 다음과 같이 사용해야합니다. parallel --pipe --block 10M "/ usr / bin / grep -F -C5 -e 'Animal Care & Pets'"
zw963

<병렬 명령 앞의 문자 는 무엇을 의미 합니까?
elcortegano

1
@elcortegano : 이것이 바로 I / O 리디렉션 입니다. 기본적으로 다음 파일 이름에서 입력을 읽습니다. 유사 cat file.sql | parallel ...하지만 UUOC를 피합니다 . GNU 병렬은 .NET을 사용하여 파일에서 입력을 읽는 방법도 있습니다 parallel ... :::: file.sql. HTH.
Steve

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 grep도 큰 차이를 만들었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.