GNU를 사용하여 매우 긴 줄을 병렬로 처리하기

GNU를 사용하여 매우 긴 줄을 병렬로 처리하기

데이터베이스에 다시 로드하기 전에 편집(일부 찾기/바꾸기)해야 하는 매우 큰 SQL 덤프 파일(30GB)이 있습니다.

파일 크기가 클 뿐만 아니라 매우 긴 줄도 포함되어 있습니다. 처음 40개 행과 마지막 12개 행을 제외하고 다른 모든 행의 길이는 약 1MB입니다. 다음 줄은 모두 INSERTO INTO 명령이며 모두 비슷해 보입니다.

cat bigdumpfile.sql | cut -c-100
INSERT INTO `table1` VALUES (951068,1407592,0.0267,0.0509,0.121),(285
INSERT INTO `table1` VALUES (238317,1407664,0.008,0.0063,0.1286),(241
INSERT INTO `table1` VALUES (938922,1407739,0.0053,0.0024,0.031),(226
INSERT INTO `table1` VALUES (44678,1407886,0.0028,0.0028,0.0333),(234
INSERT INTO `table1` VALUES (910412,1407961,0.001,0.0014,0),(911017,1
INSERT INTO `table1` VALUES (903890,1408050,0.0066,0.01,0.0287),(9095
INSERT INTO `table1` VALUES (257090,1408136,0.0023,0.0037,0.0196),(56
INSERT INTO `table1` VALUES (593367,1408237,0.0066,0.0117,0.0286),(95
INSERT INTO `table1` VALUES (870488,1408339,0.0131,0.009,0.0135),(870
INSERT INTO `table1` VALUES (282798,1408414,0.0015,0.014,0.014),(2830
...

평행선은 긴 줄 ​​오류로 끝납니다.

parallel -a bigdumpfile.sql -k sed -i.bak 's/table1/newtable/'
parallel: Error: Command line too long (1018952 >= 63543) at input 0: INSERT INTO `table1...

모든 줄이 비슷했기 때문에 줄의 시작 부분에서만 찾기/바꾸기만 하면 되었기 때문에 조언을 따랐습니다.이 비슷한 질문에서--recstart그리고 및 사용에 대한 좋은 제안을 했습니다 --recend. 그러나 이것들은 작동하지 않습니다:

parallel -a bigdumpfile.sql -k --recstart 'INSERT' --recend 'VALUES' sed -i.bak 's/table/newtable/'
parallel: Error: Command line too long (1018952 >= 63543) at input 0: INSERT INTO `table1...

여러 가지 사용법을 시도했지만 --block제대로 작동하지 못했습니다. 저는 GNU 병렬 처리의 초보자이고 뭔가 잘못하고 있거나 명백한 것을 놓치고 있습니다. 도움을 주시면 감사하겠습니다. 감사해요!

이것이 사용됩니다 GNU parallel 20240122.

답변1

--pipe( 또는 )를 사용해야 합니다 --pipepart. 디스크 속도가 빠른 경우:

parallel -a bigdumpfile.sql --pipe-part --block 100M -k -q sed 's/table1/newtable/' | sql ...

속도가 느린 경우:

parallel -j1 -a bigdumpfile.sql --pipe-part --block 100M -k -q sed 's/table1/newtable/' | sql ...

-j디스크에 가장 적합한 옵션을 찾으려면 조정하세요 .

여러 삽입을 병렬로 실행하려면 다음을 수행하십시오.

# Create the table
head -n 40 bigdumpfile.sql | sql ...
# do the INSERTs in parallel
do_ins() {
  grep 'INSERT INTO' |
    sed s/table1/newtable/ |
    sql ...
}
export -f do_ins
parallel -a bigdumpfile.sql --pipe-part --block -1 do_ins

그러나 Stéphane Chazelas가 제안했듯이 이렇게 하는 것이 더 빠를 수도 있습니다.

sed s/table1/newtable/ bigdumpfile.sql | sql some-database

관련 정보