太慢的 gzip -d 命令的替代方案

太慢的 gzip -d 命令的替代方案

我正在使用生产服务器将大型数据集加载到Hadoop访问来自蜂巢桌子。

我们正在加载电信部门的订户网页浏览数据。我们有大量.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并附加到数据文件,而不需要解压缩。

答案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}"
}

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

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

答案2

那么这个hive和hadoop呢?当您提供gzip -d“原始文件列表”时,可能会不必要地绕过该分布式文件系统。

该生产服务器上的某些内容肯定无法正常工作。一小时解压20GB(我省略了细节)。我在 0.8 秒内解压了 100 MB、分成 11300 个文件的文件。这大约快了 20 倍。使用 naiv 巨大文件列表 gzip 调用和 ram 磁盘。我还按照建议安装并尝试了并行。速度快了 10%:0.7 秒。所以这不是问题。

(我只有 8 GB 内存的 Mini-PC i5)

我有一个正在运行的瓦特表。在 14 秒的慢速循环中,使用了 6 W。
在我的可疑循环中,它的功率约为 17 W,持续 6 秒。 (提示,也是 X 服务器,为 3.5 W,susp-to-ram 为 1.1,关闭为...0.7 瓦)

在我的测试中,14 s 循环与 0.8 s 巨大参数列表的比率与您的总体 25 GB/h 与我的 100 MB/0.8 s 的比率相同:二十倍...就好像您使用的是慢速 for 循环一样。我认为 hadoop 和 hive 的巨大参数列表正在干扰 gzip 和 bash。

相关内容