Linux

替代太慢的 gzip -d 命令

  • July 3, 2019

我正在使用生產伺服器將大型數據集載入到Hadoop以從Hive表訪問。

我們正在載入電信部門的訂戶網路瀏覽數據。我們有大量使用**.csv.gz 壓縮**的文件(文件大小約為 300-500MB)gzip。假設一個文件如下:

文件名:dna_file_01_21090702.csv.gz

內容:

A,B,C,2

D,E,F,3

我們解壓縮 50 個左右的文件並連接到一個文件。出於故障排除的目的,我們將文件名附加為每一行的第一列。

所以連接數據文件將是:

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 個小時,這是巨大的。以這種速度,不可能處理一天內產生的所有數據。

我的生產伺服器(VM)非常強大。總核心為 44,RAM 為 256GB。硬碟也非常好和高性能。IOwait 在 0-5 左右。

我怎樣才能加快這個過程?的替代品是什麼gzip -d。有沒有其他方法可以更有效地連接數據文件。請注意,我們需要將文件名保存在記錄中,以便進行故障排除。

否則,我們可以只使用zcat並附加到數據文件而根本不解壓縮。

有很多磁碟 I/O 可以用管道代替。獲取一個包含 50 個壓縮文件的func_create_dat_file列表,讀取每個文件並寫入未壓縮的數據。然後,它讀取 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}"
}

這裡壓縮數據從磁碟讀取一次。未壓縮的數據被寫入管道一次,從管道讀取一次,然後寫入磁碟一次。數據的轉換與讀取並行發生,因此可以使用 2 個 CPU。

$$ Edit $$評論要求解釋該sed "s/^/${f%.gz}|/"部分。這是將文件名作為新欄位放在每行開頭的程式碼。$f是文件名。${f%.gz}從字元串的末尾刪除.gz|在這種情況下,沒有什麼特別之處,刪除尾隨後跟.${f%.gz}|的文件名也是如此。in是替換(replace)命令,它需要一個作為零件。因為正則表達式匹配行首,所以把它放在一起說將行首更改為不帶尾隨和. 這.gz``|``sed s/old/new/``regular expression``old``^``.gz``|``|添加以匹配 OP 的程序而不是 OP 的描述。如果它真的是 CSV(逗號分隔變數)文件,那麼這應該是逗號而不是豎線。

引用自:https://unix.stackexchange.com/questions/528094