매일 약 200,000줄씩 늘어나는 파일이 있는데, 모두 다음과 같이 세 줄로 이루어진 덩어리로 구성되어 있습니다.
1358726575123 # key
Joseph Muller # name
carpenter # job
9973834728345
Andres Smith
student
7836472098652
Mariah Anthony
dentist
이제 약 10,000개의 주요 패턴을 추출한 또 다른 파일이 있습니다 1358726575123
. 그런 다음 for
이러한 패턴으로 루프를 실행하고 첫 번째 파일과 비교해야 합니다. 파일에 이러한 패턴이 포함되어 있지 않으면 추가 처리를 위해 세 번째 파일에 패턴을 저장합니다.
for number in $(grep -o '[0-9]\{12\}' file2); do # finds about 10.000 keys
if ! grep -q ^$number$ file1; then # file1 is a huge file
printf "$number\n" >>file3 # we'll process file3 later
fi
done
예제 코드는 큰 파일을 10,000번 grep합니다. 저는 이 루프를 대략 10,000번 실행합니다.1분에 한 번, 하루 종일.
대용량 파일이 계속해서 커지는데, 이 모든 것을 더 빠르게 만들고 일부 CPU를 절약하려면 어떻게 해야 합니까? 키별로 파일을 정렬하거나(그렇다면 어떻게?) 일반 텍스트 대신 데이터베이스를 사용하는 것이 도움이 될지 궁금합니다.
답변1
물론 문제는 큰 파일에 대해 grep을 10,000번 실행한다는 것입니다. 두 파일을 한 번만 읽어야 합니다. 스크립팅 언어를 사용하지 않으려면 다음을 수행할 수 있습니다.
- 파일 1에서 모든 숫자를 추출하고 정렬합니다.
- 파일 2에서 모든 숫자를 추출하고 정렬합니다.
comm
두 번째 목록에 있는 내용만 얻으려면 정렬된 목록을 실행하세요.
이 같은:
$ grep -o '^[0-9]\{12\}$' file1 | sort -u -o file1.sorted
$ grep -o '[0-9]\{12\}' file2 | sort -u -o file2.sorted
$ comm -13 file1.sorted file2.sorted > file3
바라보다 man comm
.
로그 파일과 같은 대용량 파일을 매일 자를 수 있다면 정렬된 숫자의 캐시를 유지할 수 있으며 매번 구문 분석할 필요가 없습니다.
답변2
awk
이 답변은 게시된 답변을 기반으로 합니다.포통.. 동일한 상황에서 이 방법(내 시스템에서)
보다 두 배 빠릅니다.comm
600만 행메인 파일과10000키... (이제 FNR, NR을 사용하도록 업데이트됨)
현재 시스템보다 빠르며 awk
귀하와 귀하의 컴퓨터에 약간의 여유 공간을 제공하지만 데이터 처리가 설명만큼 집중적일 경우 전용 데이터베이스로 전환하면 최상의 전체 결과를 얻을 수 있다는 점에 유의하십시오. SQLite, MySQL...
awk '{ if (/^[^0-9]/) { next } # Skip lines which do not hold key values
if (FNR==NR) { main[$0]=1 } # Process keys from file "mainfile"
else if (main[$0]==0) { keys[$0]=1 } # Process keys from file "keys"
} END { for(key in keys) print key }' \
"mainfile" "keys" >"keys.not-in-main"
# For 6 million lines in "mainfile" and 10 thousand keys in "keys"
# The awk method
# time:
# real 0m14.495s
# user 0m14.457s
# sys 0m0.044s
# The comm method
# time:
# real 0m27.976s
# user 0m28.046s
# sys 0m0.104s
답변3
예, 반드시 데이터베이스를 사용하세요. 이러한 유형의 작업을 위해 설계되었습니다.
답변4
데이터가 너무 많으면 데이터베이스로 전환해야 합니다. 동시에 적절한 성능에 근접하기 위해 해야 할 일은 file1
각 키를 개별적으로 검색하지 않는 것입니다. grep
한 번에 제외되지 않은 모든 키를 추출하려면 한 번 실행하세요 . 키가 포함되지 않은 행도 반환 되므로 grep
필터링됩니다.
grep -o '[0-9]\{12\}' file2 |
grep -Fxv -f - file1 |
grep -vx '[0-9]\{12\}' >file3
( -Fx
문자 그대로 전체 행을 검색하는 것을 의미합니다. -f -
표준 입력에서 패턴 목록을 읽는 것을 의미합니다.)