替代太慢的 gzip -d 命令

Mil*_*ker 0 linux performance gzip shell-script

我正在使用生产服务器将大数据集加载到Hadoop以从Hive表访问。

我们正在加载电信部门的订户网页浏览数据。我们有大量.csv.gz文件(文件大小约为 300-500MB),它们使用.csv文件压缩gzip。假设一个文件如下:

文件名:dna_file_01_21090702.csv.gz

内容:

A,B,C,2

D,E,F,3

我们解压缩 50 个左右的文件并连接到一个文件。出于故障排除目的,我们将文件名附加为每行的第一列。
所以 concatenet 数据文件将是:

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
Run Code Online (Sandbox Code Playgroud)

现在的问题是gzip -d命令执行速度非常慢。我的意思是真的很慢。如果它解压缩 50 个文件并制作连接的数据文件,则大小约为 20-25GB。

解压缩 50 个文件并将其连接为一个需要将近 1 小时,这是巨大的。以这种速度,不可能在一天内处理所有生成的数据。

我的生产服务器(VM)非常强大。总核心为 44,RAM 为 256GB。硬盘也非常好,性能高。IOwait 大约为 0-5。

我怎样才能加快这个过程?的替代品是什么gzip -d。有没有其他方法可以使连接的数据文件更有效。请注意,我们需要将文件名保留在记录中以进行故障排除。

否则,我们可以直接使用zcat并附加到数据文件中,而无需解压。

ica*_*rus 5

有很多磁盘 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}"
}
Run Code Online (Sandbox Code Playgroud)

这里从磁盘读取一次压缩数据。未压缩的数据一次写入管道,从管道读取一次,然后写入磁盘一次。数据的转换与读取并行发生,因此可以使用 2 个 CPU。

[编辑] 要求解释该sed "s/^/${f%.gz}|/"部分的评论。这是将文件名作为新字段放在每行开头的代码。$f是文件名。从字符串的末尾${f%.gz}删除.gz|在这种情况下,没有什么特别之处,${f%.gz}|文件名.gz删除尾随后跟一个|. insed s/old/new/是替代(replace)命令,它regular expressionold零件取a 。^由于正则表达式匹配行首,因此将它们放在一起表示将行首更改为不带尾随的文件名.gz|. 这|添加是为了匹配 OP 的程序而不是 OP 的描述。如果它真的是一个 CSV(逗号分隔的变量)文件,那么这应该是一个逗号而不是一个竖线。