快速将70,000个文件加载到数组中并插入数据库

时间:2012-09-07 20:35:56

标签: arrays bash

几天前,我的脚本处理了我们的EMC群发文件中的大量文件,我遇到了问题。现在是我的工作代码

unset xP_Array
declare -a xP_Array
...
export LOG=$HOME/BIN/somelogfile
export OUT=/path/to/device
...
echo "`date '+%m/%d/%y %T:'` START -- MEM"                          >> $LOG

echo "`date '+%m/%d/%y %T:'` Go to work directory."                                              >> $LOG
cd ${OUT}

echo "`date '+%m/%d/%y %T:'` Fill the array."                                                   >> $LOG
for f in "$OUT"/*XML; do
    xP_Array+=( "${f#$OUT/}" )
done
echo "`date '+%m/%d/%y %T:'` Get array length."                                               >> $LOG
Plen=${#xP_Array[@]}

echo "`date '+%m/%d/%y %T:'` MEM: $Plen FILES TO PROCESS."                                      >> $LOG

echo "`date '+%m/%d/%y %T:'` Check if zero files."                                               >> $LOG
date_fmt='%m/%d/%y %T'
if (( Plen = 0 ))
then
    printf "%($date_fmt)T: ZERO FILES\n" $(date +%s)                                            >> $LOG
fi

echo "`date '+%m/%d/%y %T:'` Loop."                                                             >> $LOG
for i in "${xP_Array[@]}"
do
        echo "`date '+%m/%d/%y %T:'` Move file to run directory."                              >> $LOG
        mv $OUT/$i RUN/
        echo "`date '+%m/%d/%y %T:'` PROCESSING "$i"."                                          >> $LOG
        [[[DATABASE LOAD DONE HERE]]]
        echo "`date '+%m/%d/%y %T:'` Check DB LOAD return value."                                       >> $LOG
        EXIT=`echo $?`
        case $EXIT in
                0) echo "`date '+%m/%d/%y %T:'` COMPLETE."                                      >> $LOG
                mv RUN/"$i" "$ARCH"
                ;;
                *) echo "`date '+%m/%d/%y %T:'` ERROR. "$i" MOVED TO RECON."                    >> $LOG
                mv RUN/"$i" "$RECON"
                ;;
        esac
done

echo "`date '+%m/%d/%y %T:'` END -- MEM"                                    >> $LOG

我想知道它是否可以更快地运作。我已经在使用我的DBA来查看数据库插入是否可以加速,但我想知道循环本身是否可以更快地运行。

顺便说一下,所有echo语句都被重定向到一个日志文件,我在脚本完成时自己发送电子邮件。他们放慢了脚本的速度吗?

可以优化此脚本以更快地运行吗?

2 个答案:

答案 0 :(得分:2)

我在这里唯一能想到的是echo "date...语句和CASE语句,但这些语句的执行时间应该可以忽略不计。我会集中精力调整SQL,而不是花时间在这里微调bash脚本。如果您真的想在脚本中执行某些操作,可以使用@chepner提到的提示。

另一种方式是,如果您的文件格式相同,那么您可以合并所有文件,或者一次合并100个文件作为CSV文件,然后使用合并的CSV文件加载External Tables。然后,您可以使用外部表加载实际表。您可以使用外部表一次一个文件开始执行该操作,并查看观察到的性能差异。

对于数据文件(如果格式正确),外部表是非常方便的解决方案,因为如果数据文件存在于指定目录中,则根本不需要INSERT和/或DELETE工作您将在表中找到您不会发现的数据(如果数据文件不存在,在表上发出SELECT将导致错误并生成一些log文件,这些文件很容易处理)。

答案 1 :(得分:1)

for f in "$OUT"/*XML; do
    xP_Array+=( "${f#$OUT/}" )
done

可以替换为

pushd "$OUT"
xP_Array=( *XML )
popd

但我不认为这是你剧本中的一大瓶颈。

在你的另一个循环中,我看到的唯一真正的开销是重复调用date和 使用命令替换将$?分配给EXIT,这可以直接完成(EXIT=$?)。除了实际的DB负载之外,我认为除了实际的数据库负载之外还有其他任何优化。

如果您愿意从人类可读日期切换,您可以将当前时间(作为UNIX时间戳)分配给SECONDS,然后仅引用该日志行的变量而不是调用date

SECONDS=$(date +%s)
for i in "${xP_Array[@]}"
do
    echo "$SECONDS: Move file to run directory." >> $LOG
    # etc
done

使用足够新的bash(我认为4.2或更高版本),printf可以将UNIX时间戳格式化为可读时间:

printf "%(%m/%d/%Y %T)T" $SECONDS