Split과 함께 GNU Parallel 사용


9

postgresql 데이터베이스에 꽤 거대한 파일을로드하고 있습니다. 이를 위해 먼저 split파일에서 더 작은 파일 (각각 30Gb)을 얻기 위해 사용한 다음 GNU Paralleland을 사용하여 더 작은 파일을 데이터베이스에로드합니다 psql copy.

문제는 파일을 분할하는 데 약 7 시간이 걸리고 코어 당 파일을로드하기 시작한다는 것입니다. 필요한 것은 split파일 작성이 완료 될 때마다 파일 이름을 std 출력으로 인쇄하여 파이프 할 수 Parallel있고 파일 split작성이 완료 되면 파일로드를 시작 하도록 지시 하는 방법입니다. 이 같은:

split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}

split매뉴얼 페이지를 읽었으며 아무것도 찾을 수 없습니다. 이 split도구 나 다른 도구를 사용 하여이 작업을 수행 할 수 있습니까?

답변:


13

--pipe를 사용하십시오 :

cat 2011.psv | parallel --pipe -l 50000000 ./carga_postgres.sh

파일이 아닌 stdin에서 읽으려면 ./carga_postgres.sh가 필요하며 GNU Parallel 버전 <20130222의 경우 속도가 느립니다.

정확히 50000000 줄이 필요하지 않으면 --block이 더 빠릅니다.

cat 2011.psv | parallel --pipe --block 500M ./carga_postgres.sh

\ n에 약 500MB 분할 청크를 전달합니다.

./carga_postgres.sh에 무엇이 포함되어 있는지 모르지만 사용자 이름 비밀번호가있는 psql이 포함되어 있습니다. 이 경우 GNU Parallel (GNU Parallel의 일부) 인 GNU SQL을 사용할 수 있습니다.

cat 2011.psv | parallel --pipe --block 500M sql pg://user:pass@host/db

가장 큰 장점은 임시 파일을 저장할 필요는 없지만 메모리 / 파이프에 모두 저장할 수 있다는 것입니다.

./carga_postgres.sh가 stdin에서 읽을 수 없지만 파일에서 읽어야하는 경우 파일로 저장할 수 있습니다.

cat 2011.psv | parallel --pipe --block 500M "cat > {#}; ./carga_postgres.sh {#}"

대규모 작업은 종종 절반 정도 실패합니다. GNU Parallel은 실패한 작업을 다시 실행하여 도움을 줄 수 있습니다.

cat 2011.psv | parallel --pipe --block 500M --joblog my_log --resume-failed "cat > {#}; ./carga_postgres.sh {#}"

이것이 실패하면 위의 내용을 다시 실행할 수 있습니다. 이미 성공적으로 처리 된 블록을 건너 뜁니다.


1
최신 버전의 GNU Parallel> 20140422를 사용하는 경우 --pipepart와 함께 @RobertB의 답변을 사용하십시오. 그래도 문제가 해결되지 않으면 --fifo 또는 --cat가 도움이 될 수 있는지 확인하십시오.
Ole Tange

2

GNU Parallel과 함께 --pipe AND --pipepart를 사용하지 않는 이유는 무엇입니까? 그러면 추가 고양이가 제거되고 디스크의 파일에서 직접 읽기가 시작됩니다.

parallel --pipe --pipepart -a 2011.psv --block 500M ./carga_postgres.sh

1

여기에 게시 된 답변이 복잡한 방법이라는 것을 알았으므로 Stack Overflow에 요청 하고이 답변을 얻었습니다 .

를 사용 GNU split하는 경우 --filter옵션 으로이 작업을 수행 할 수 있습니다

'--filter = command'
이 옵션을 사용하면 단순히 각 출력 파일에 쓰지 않고 파이프를 통해 각 출력 파일에 대해 지정된 쉘 명령에 쓰십시오. 명령은 $ FILE 환경 변수를 사용해야합니다.이 변수는 명령을 호출 할 때마다 다른 출력 파일 이름으로 설정됩니다.

쉘 스크립트를 작성하면 파일을 작성하고 백그라운드에서 끝에 carga_postgres.sh를 시작할 수 있습니다.

#! /bin/sh

cat >$FILE
./carga_postgres.sh $FILE &

해당 스크립트를 필터로 사용하십시오.

split -l 50000000 --filter=./filter.sh 2011.psv

0

split파일 이름 을 인쇄 하는 대안 은 파일이 준비된시기를 감지하는 것입니다. Linux에서는 inotify 기능, 특히 inotifywait유틸리티를 사용할 수 있습니다 .

inotifywait -m -q -e close_write --format %f carga | parallel ./carga_postgres.sh &
split -l 50000000 2011.psv carga/2011_

inotifywait수동으로 죽여야 합니다. 잠재적 경쟁 조건이 있기 때문에 자동으로 종료하는 것은 약간 어렵습니다. split완료 하자마자 종료하면 아직보고되지 않은 이벤트가 수신되었을 수 있습니다. 모든 이벤트가보고되도록하려면 일치하는 파일을 계산하십시오.

{
  sh -c 'echo $PPID' >inotifywait.pid
  exec inotifywait -m -q -e close_write --format %f carga
} | tee last.file \
  | parallel ./carga_postgres.sh &
split -l 50000000 2011.psv carga/2011_
(
  set carga/2011_??; eval "last_file=\${$#}"
  while ! grep -qxF "$last_file" last.file; do sleep 1; done
)
kill $(cat inotifywait.pid)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.