遅すぎる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(カンマ区切り変数)ファイルの場合は、パイプではなくコンマでなければなりません。

答え2

それでは、HiveとHadoopはどうでしょうか? 「生ファイルのリスト」を提供すると、gzip -d不必要に分散ファイルシステムをバイパスすることができます。

その本番サーバーで間違いなく何かが正常に動作しません。 1時間以内に20GBが解凍されます(詳細は省略しました)。 100MBファイルを11,300ファイルに分割し、0.8秒で解凍しました。これは約20倍速い速度です。 naiv huge file list gzip 呼び出しと ram ディスクを使用します。また、提案されているようにインストールし、並列を試みました。 10%速くなる:0.7秒。したがって、これは問題ではありません。

(私は8GBのRAMを備えたMini-PC i5のみを持っています。)

私は実行中の電力計を持っています。 14秒の遅いサイクルでは、6Wが使用されました。
私の疑わしいループでは、6秒間約17Wでした。 (ヒント、Xサーバーでもあります。3.5W、Susp-to-RAMは1.1、オフは... 0.7W)

私のテストでは、大規模パラメータリストの14秒ループ対0.8秒の比率は、私の100MB / 0.8秒の合計25GB / hの割合と同じです。 20倍...遅いforループと同じです。 hadoopとhiveの巨大なパラメータリストがgzipとbashを妨げていると思います。

関連情報