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


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.