使用GNU并行拆分

问题描述 投票:12回答:2

我正在将一个非常巨大的文件加载到postgresql数据库中。为此,我首先在文件中使用split来获取较小的文件(每个30Gb),然后使用GNU Parallelpsql copy将每个较小的文件加载到数据库。

问题是分割文件大约需要7个小时,然后开始为每个核心加载一个文件。我需要的是告诉split每次完成文件写入时将文件名打印到std输出的方法,这样我就可以将它传送到Parallel,并在split完成编写时开始加载文件。像这样的东西:

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

我已经阅读了split手册页,我找不到任何东西。有没有办法用split或任何其他工具做到这一点?

bash split gnu-parallel
2个回答
24
投票

你可以让并行执行拆分:

<2011.psv parallel --pipe -N 50000000 ./carga_postgres.sh

请注意,该联机帮助页建议在--block上使用-N,这仍然会将记录分隔符\n的输入拆分为默认值,例如:

<2011.psv parallel --pipe --block 250M ./carga_postgres.sh

Testing --pipe and -N

这是一个将100个数字序列分成5个文件的测试:

seq 100 | parallel --pipe -N23 'cat > /tmp/parallel_test_{#}'

检查结果:

wc -l /tmp/parallel_test_[1-5]

输出:

 23 /tmp/parallel_test_1
 23 /tmp/parallel_test_2
 23 /tmp/parallel_test_3
 23 /tmp/parallel_test_4
  8 /tmp/parallel_test_5
100 total

EDIT:

如果分割文件太多,请使用ls -v按数字顺序对输出进行排序。

# to list files
ls -v1 /tmp/parallel_test*
# to merge
cat $(ls -v1 /tmp/parallel_test*) > merged.txt

2
投票

如果使用GNU split,可以使用--filter选项执行此操作

“--filter =命令” 使用此选项,而不是简单地写入每个输出文件,通过管道写入每个输出文件的指定shell命令。命令应该使用$ FILE环境变量,该变量在每次调用命令时设置为不同的输出文件名。

您可以创建一个shell脚本,该脚本创建一个文件并在后台的末尾启动carga_postgres.sh

#! /bin/sh

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

并使用该脚本作为过滤器

split -l 50000000 --filter=./filter.sh 2011.psv
© www.soinside.com 2019 - 2024. All rights reserved.