1

几天前,我在处理我们的 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当脚本完成时,所有语句都被重定向到我自己通过电子邮件发送的日志文件。他们是否减慢了脚本的速度?

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

4

2 回答 2

2

我在这里唯一能想到的是echo "date...语句和CASE语句,但它们的执行时间应该可以忽略不计。我会更专注于调整 SQL,而不是花时间在这里微调 bash 脚本。如果你真的想在脚本中做一些事情,你可以使用@chepner 提到的技巧。

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

当涉及到数据文件(如果格式正确)时,外部表是非常方便的解决方案,因为实际上不需要INSERTDELETE需要努力,如果数据文件存在于指定目录中,您将在表中找到数据,否则您不会(如果数据文件不存在,在表上发出 aSELECT会导致错误,并会生成一些log可以轻松处理的文件)。

于 2012-09-07T22:02:47.197 回答
1
for f in "$OUT"/*XML; do
    xP_Array+=( "${f#$OUT/}" )
done

可以替换为

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

但我认为这不是您脚本中的一大瓶颈。

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

如果您愿意从人类可读的日期切换,您可以将当前时间(作为 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
于 2012-09-07T21:03:04.677 回答