너무 느린 gzip -d 명령의 대안

너무 느린 gzip -d 명령의 대안

프로덕션 서버를 사용하여 대규모 데이터세트를 로드하고 있습니다.하둡다음에서 방문함벌집테이블.

통신 부문의 가입자 웹 브라우징 데이터를 로드하고 있습니다. 우리는 많은 것을 가지고 있습니다.csv.gz파일(파일 크기는 약 300-500MB)을 사용합니다 gzip. 파일이 다음과 같다고 가정합니다.

파일 이름: dna_file_01_21090702.csv.gz

콘텐츠:

에이,비,씨,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_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. |In sed s/old/new/은 교체(replace) 명령이므로 regular expression해당 old부분을 나타내야 합니다. ^정규 표현식이 줄의 시작 부분과 일치하기 때문에 함께 사용하면 OP의 설명이 아닌 OP의 프로그램과 일치하도록 추가 .gz되었습니다 |. |실제로 CSV(쉼표로 구분된 변수) 파일인 경우 파이프가 아닌 쉼표여야 합니다.

답변2

그렇다면 하이브와 하둡은 어떨까요? "원시 파일 목록"을 제공하면 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를 방해하고 있다고 생각합니다.

관련 정보