遅すぎるgzip -dコマンドの代替

遅すぎるgzip -dコマンドの代替

本番サーバーを使用して大規模なデータセットをロードしています。Hadoop次から訪問しましたハニカムテーブル。

通信部門の加入者Web閲覧データをロードしています。私たちは多くのものを持っています.csv.gzファイル(ファイルサイズは約300〜500 MB)を使用してくださいgzip。ファイルが次のようになるとします。

ファイル名: dna_file_01_21090702.csv.gz

コンテンツ:

A、雨、種、2

DEF3

約50個のファイルを解凍し、1つのファイルにリンクしました。トラブルシューティングのために、各行の最初の列にファイル名を追加します。
したがって、リンクされたデータファイルは次のようになります。

dna_file_01_21090702.csv.gz,A,B,C,2

dna_file_01_21090702.csv.gz,D,E,F,33

これを行うには、次のbashスクリプトを作成します。

#!/bin/bash
func_gen_new_file_list()
{
        > ${raw_file_list}
        ls -U raw_directory| head -50 >> ${raw_file_list}
}
func_create_dat_file()
{
        cd raw_directory
        gzip -d `cat ${raw_file_list}`
        awk '{printf "%s|%s\n",FILENAME,$0}' `cat ${raw_file_list}|awk -F".gz" '{print $1}'` >> ${data_file}
}
func_check_dir_n_load_data()
{
        ## Code to copy data file to HDFS file system 
}
##___________________________ Main Function _____________________________
        ##__Variable            
        data_load_log_dir=directory
        raw_file_list=${data_load_log_dir}/raw_file_list_name
        data_file_name=dna_data_file_`date "+%Y%m%d%H%M%S"`.dat
        data_file=${data_load_log_dir}/${data_file_name}

        ##__Function Calls
        func_gen_new_file_list
        func_create_dat_file
        func_check_dir_n_load_data

今問題は、gzip -dコマンドの実行が非常に遅いことです。本当に本当に遅いという意味です。 50個のファイルを解凍してまとめたデータファイルを作ると、サイズは約20~25GB程度になります。

50個のファイルを解凍して1つのファイルにまとめるのに約1時間かかります。この速度では、1日に生成されるすべてのデータを処理することは不可能です。

私の本番サーバー(VM)は非常に強力です。総コア数は44個、RAMは256GBです。ハードドライブも非常に良く、パフォーマンスが良いです。 IOwaitは約0〜5です。

このプロセスをスピードアップするにはどうすればよいですか? 。gzip -dデータファイルをより効率的にリンクする他の方法はありますか?トラブルシューティングのためにファイル名を保存する必要があります。

zcatそれ以外の場合は、解凍せずにデータファイルを使用して追加できます。

ベストアンサー1

パイプに置き換えることができるディスクI / Oがたくさんあります。func_create_dat_file50個の圧縮ファイルのリストを取得し、各ファイルを読み取り、圧縮されていないデータを書き込みます。次に、圧縮されていない50個のデータファイルをそれぞれ読み取り、ファイル名の前に書き換えます。これらの作業はすべて順次実行されるため、複数のCPUを完全に活用することはできません。

私はあなたがそれを試すことをお勧めします

func_create_dat_file()
{
    cd raw_directory
    while IFS="" read -r f
    do
        zcat -- "$f" | sed "s/^/${f%.gz}|/"
    done < "${raw_file_list}" >> "${data_file}"
}

ここでは、圧縮データをディスクから一度読み込みます。圧縮されていないデータはパイプに一度書き込まれ、パイプから読み取られた後、ディスクに一度書き込まれます。データ変換は読み出しと並行して行われるため、2CPUを使用できます。

[編集] このセクションの説明を求めるコメントですsed "s/^/${f%.gz}|/"。以下は、各行の先頭にファイル名を新しいフィールドとして追加するコードです。$fファイル名です。文字列の末尾から削除します${f%.gz}。この場合、.gz特別なものはありません|${f%.gz}|ファイル名も同様です。末尾を削除します.gz|Insed s/old/new/は置換コマンドであるため、そのregular expression部分oldを表す必要があります。^正規表現が行の先頭に一致するため、一緒に使用すると、OPの説明ではなくOPのプログラムと一致するように追加され.gzました||実際にCSV(カンマ区切り変数)ファイルの場合は、パイプではなくコンマでなければなりません。

おすすめ記事