我正在将一个非常巨大的文件加载到postgresql数据库中。为此,我首先在文件中使用split
来获取较小的文件(每个30Gb),然后使用GNU Parallel
和psql copy
将每个较小的文件加载到数据库。
问题是分割文件大约需要7个小时,然后开始为每个核心加载一个文件。我需要的是告诉split
每次完成文件写入时将文件名打印到std输出的方法,这样我就可以将它传送到Parallel
,并在split
完成编写时开始加载文件。像这样的东西:
split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}
我已经阅读了split
手册页,我找不到任何东西。有没有办法用split
或任何其他工具做到这一点?
你可以让并行执行拆分:
<2011.psv parallel --pipe -N 50000000 ./carga_postgres.sh
请注意,该联机帮助页建议在--block
上使用-N
,这仍然会将记录分隔符\n
的输入拆分为默认值,例如:
<2011.psv parallel --pipe --block 250M ./carga_postgres.sh
--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
如果分割文件太多,请使用ls -v
按数字顺序对输出进行排序。
# to list files
ls -v1 /tmp/parallel_test*
# to merge
cat $(ls -v1 /tmp/parallel_test*) > merged.txt
如果使用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