我正在将一个非常巨大的文件加载到postgresql数据库中。为此,我首先在文件中使用split
来获取较小的文件(每个30Gb),然后使用GNU Parallel
和psql copy
将每个较小的文件加载到数据库。
问题是分割文件大约需要7个小时,然后开始为每个核心加载一个文件。我需要的是一种告诉split
每次完成文件写入时将文件名打印到std输出的方法,这样我就可以将它传递给Parallel
并开始加载文件split
1}}完成它的写作。像这样:
split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}
我已阅读split
手册页,但找不到任何内容。有没有办法用split
或任何其他工具执行此操作?
答案 0 :(得分:24)
你可以让并行执行拆分:
<2011.psv parallel --pipe -N 50000000 ./carga_postgres.sh
请注意,该联机帮助页建议使用--block
而不是-N
,默认情况下仍会将记录分隔符\n
拆分,例如:
<2011.psv parallel --pipe --block 250M ./carga_postgres.sh
--pipe
和-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
答案 1 :(得分:2)
如果您使用GNU split
,则可以使用--filter
选项
“ - 滤波器=命令”
使用此选项,而不是简单地写入每个输出文件,通过管道写入每个输出文件的指定shell命令。命令应该使用$ FILE环境变量,该变量在每次调用命令时设置为不同的输出文件名。
你可以创建一个shell脚本,它创建一个文件并在后台的末尾启动carga_postgres.sh
#! /bin/sh
cat >$FILE
./carga_postgres.sh $FILE &
并将该脚本用作过滤器
split -l 50000000 --filter=./filter.sh 2011.psv