本番サーバーを使用して大規模なデータセットをロードしています。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_file
50個の圧縮ファイルのリストを取得し、各ファイルを読み取り、圧縮されていないデータを書き込みます。次に、圧縮されていない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を妨げていると思います。