대용량 파일에 대한 성능 향상


10

30 만 줄이 넘는 FILE_A와 3 천만 줄이 넘는 FILE_B가 있습니다. FILE_A에서 FILE_A의 각 줄을 grep하고 grep의 결과를 새 파일에 쓰는 Bash 스크립트를 만들었습니다 .

이 전체 프로세스는 5 시간 이상이 걸립니다.

스크립트 성능을 개선하려면 어떻게해야합니까?

grep -F -m 1grep 명령으로 사용 하고 있습니다. FILE_A는 다음과 같습니다.

123456789 
123455321

FILE_B는 다음과 같습니다.

123456789,123456789,730025400149993,
123455321,123455321,730025400126097,

Bash를 사용 while하면 FILE_A에서 다음 줄을 선택하고 FILE_B에서 greps 하는 루프가 있습니다. FILE_B에서 패턴을 찾으면 result.txt 파일에 씁니다.

while read -r line; do
   grep -F -m1 $line 30MFile
done < 300KFile

답변:


17

를 사용해보십시오 grep --file==FILE_A. 거의 확실하게 패턴을 메모리에로드합니다. 즉, FILE_B를 한 번만 스캔합니다.

grep -F -m1 --file==300KFile 30MFile

메모리가 충분하다고 가정하는 경우에만 작동합니까?
— rogerio_marcio 2016 년

솔직히, 나는 그 크기의 파일에서 직접 시도하지는 않았지만 속도가 크게 향상되어야한다고 생각합니다. 최신 컴퓨터를 사용하는 경우 300K 파일을 메모리에 저장하는 데 아무런 문제가 없습니다. (또는 그 문제에 대한 30M 하나)
— 로봇 Gort

-f (--file) 옵션을 사용하면 기본적으로 30MFile을 다시 작성했습니다. 내가 뭔가 잘못하고 있습니까?
— rogerio_marcio 2

흠 ... 아마 300Kfile에 빈 줄이 있습니까?
— 로봇 고트

바로 그 자리에! 그거였다! 완벽하게 작동하여 30 초 안에 완료되었습니다! 감사합니다!!
— rogerio_marcio

2

후손에 대한 펄 답변입니다. 나는 보통 1M 라인을 30-35M 라인에 일치시키기 위해 이것을 수행합니다. 완료하는 데 약 10 초가 걸립니다.

먼저 FILE_A를 해시하십시오.

my %simple_hash;
open my $first_file, '<', 'FILE_A' or die "What have you done?! $!";
while (<$first_file>) {
  chomp;                 ## Watch out for Windows newlines
  $simple_hash{$_} = 1;  ## There may be an even faster way to define this
}
close $first_file;

그런 다음 큰 파일을 확인 후 갈 것을 열 구분하고 알고있는 경우 만 존재 하면, 많이 FILE_B, 아래 실행으로 해시 키를 훨씬 더 빨리 평등 또는 정규 표현식 일치에 대한 검사 이상 :

open my $second_file, '<', 'FILE_B' or die "Oh no, not again.. $!";
while (<$second_file>) {
  my ($col1, undef) = split ',';
  if (exists($simple_hash{$col1}) {
    print $_;
  }
}
close $second_file;

더 큰 대상 파일을 구문 분석 할 수없는 경우이 스크립트는 정규 표현식 엔진 을 실행하지 않아도되기 때문에 속도가 너무 높아져서 값을 잃습니다 .


1

더 많은 관련 프로그래밍이 마음에 들지 않으면 접미사 트리 (또는 변형)를 사용하십시오.

선형 시간으로 Ukkonen의 알고리즘 을 FILE_B사용하여 전처리 할 수 ​​있습니다 . 그런 다음 각 줄의 시간을 줄 길이로 선형으로 쿼리 하고 결과 파일에 쓸 수있는 일치하는 모든 줄 번호 (트리를 조정해야 할 수도 있음)를 가져옵니다.FILE_A

시간 O (N + ㎚) n은 길이 인 경우의 전체 공정의 실행 FILE_B, N의 행의 개수 FILE_A와 m의 가장 긴 선의 길이 FILE_A이것은 본질적으로 선형 런타임이다 -. 원래 접근 방식에 필요한 이차 시간을 규모별로 능가합니다.


1

--mmap최근 에 깃발을 찾았고 테스트 할 기회가 없었지만, 발견 한 내용에 대해 기뻐할 것입니다. 다음은 매뉴얼 페이지의 설명입니다.

--mmap If  possible, use the mmap(2) system call to read input, instead
      of the default read(2) system call.  In some situations,  --mmap
      yields  better performance.  However, --mmap can cause undefined
      behavior (including core dumps) if an input file  shrinks  while
      grep is operating, or if an I/O error occurs.

참조 이 나 이 에 대한 자세한 정보를 원하시면 mmap.


나는 이것을 확실히하려고하고 그것이 어떻게 진행되는지 알려줄 것이다. 코어 덤프가 발생할 가능성은 얼마나됩니까?
— rogerio_marcio

@rogerio_marcio 글쎄, 내가 아는 것처럼 "grep이 작동하는 동안 파일이 축소되거나 I / O 오류가 발생하면". 실제로는 아니지만 이것을 더 잘 알아야합니다. (내가 grep하는 동안 파일을 건드리지 않았다고 가정하면-이것은 일어나지 않아야 함)
— Ramzi Kahil

--mmap복용량으로 아무것도 덤프하지 않는 테스트의 경우 ,로 실행하고 그렇지 않은 런을 권장합니다 --mmap. 그리고 wc당신이 같은 양의 출력을 가지고 있음을 알기 위해 사용 하십시오-이것은 우리가 grep을 2 번 실행했고 깃발 만 다른 것을 고려한 강력한 테스트 여야합니다.
— Ramzi Kahil

@rogerio_marcio 이것을 시도 했습니까? 통찰력이 있습니까?
— Ramzi Kahil 2016 년

-1

왜 데이터베이스 데이터베이스에 파일을 넣지 않는 것이 효율적인 병합, 해시, 중첩 루프 조인을 수행하는 데 정말 좋습니다. 그리고 그들은 가상 메모리 활용에 정말 능숙합니다


다른 모든 답변으로 수행하는 모든 작업은 데이터베이스 휠을 재창조하는 것입니다.
— Andyz Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.