Gzip 압축이 중복 데이터 청크를 제거하지 않는 이유는 무엇입니까?


30

방금 중복 파일로 tar 아카이브를 작성하여 압축 여부를 확인하는 약간의 실험을했습니다. 세부 사항은 다음과 같습니다 (읽기 즐거움을 위해 들여 쓴 결과) :

$ dd if=/dev/urandom bs=1M count=1 of=a
  1+0 records in
  1+0 records out
  1048576 bytes (1.0 MB) copied, 0.114354 s, 9.2 MB/s
$ cp a b
$ ln a c
$ ll
  total 3072
  -rw-r--r-- 2 guido guido 1048576 Sep 24 15:51 a
  -rw-r--r-- 1 guido guido 1048576 Sep 24 15:51 b
  -rw-r--r-- 2 guido guido 1048576 Sep 24 15:51 c
$ tar -c * -f test.tar
$ ls -l test.tar 
  -rw-r--r-- 1 guido guido 2109440 Sep 24 15:51 test.tar
$ gzip test.tar 
$ ls -l test.tar.gz 
  -rw-r--r-- 1 guido guido 2097921 Sep 24 15:51 test.tar.gz
$ 

먼저 무작위 데이터 (a)의 1MiB 파일을 만들었습니다. 그런 다음 파일 b에 복사하고 c로도 연결했습니다. 타르볼을 생성 할 때 타르볼은 ~ 3Mib가 아닌 ~ 2MiB에 불과하므로 tar는 하드 링크를 알고있었습니다.

이제 a와 b가 중복되기 때문에 gzip이 tarball의 크기를 ~ 1MiB로 줄일 것으로 예상했지만 tarball 내부에 1MiB의 연속 데이터가 반복되어야하지만 아직 발생하지 않았습니다.

왜 이런거야? 이 경우 어떻게 tarball을 효율적으로 압축 할 수 있습니까?

답변:


24

Gzip gzip은 LZ77과 Huffman 코딩의 조합 인 DEFLATE 알고리즘을 기반으로합니다. 무손실 데이터 압축 알고리즘으로, 입력 스트림을 즉시 구축 된 사전을 사용하여 압축 기호로 변환하고 복제본을 관찰하여 작동합니다. 그러나 중복을 32K 이상으로 구분할 수는 없습니다. 1MB 떨어져있는 복제물을 발견 할 것으로 예상되는 것은 현실적이지 않습니다.


충분합니다! 스트림에서 작동하지 않는 대안을 알고 있습니까?
귀도

1
귀하의 문제에 대한 패키지 솔루션을 모르겠습니다. 이것이 반복적이고 심각한 문제가 될 것으로 예상되면 (개인적으로) 중복을 찾기 위해 n-way cmp (비교) 작업을 수행하여 스크립트를 공격하고 목록을 파일에 쓴 다음 tar + gzip 만 고유 항목 + 목록 복원하려면 두 번째 스크립트를 사용하여 압축을 풀고 압축을 풀고 목록에서 딥을 만듭니다. 다른 대안은 타르가 그 점을 발견한다는 것을 알고 있기 때문에 딥을 하드 링크로 바꾸는 것입니다. 죄송합니다. 그게 당신이 바라는 것이 아닐 수도 있습니다.
Nicole Hamilton

1
gzip과 bzip2는 디자인 때문에 상대적으로 "스트림 친화적"이어야합니다. 파이프의 일부로 작업 할 수 있어야합니다. 여기서 찾고있는 것은 실제로 압축 만이 아니라 중복 제거입니다. tar는 프로세스를 두 부분으로 나누기 때문에 tar로만 아카이브 한 다음 두 번째 프로그램을 압축 필터로 사용합니다. 검색에서 중복 제거 기능이있는 압축 된 아카이브를 찾을 수 없지만이 이전 관련 질문을 찾았습니다. superuser.com/questions/286414/…
Stephanie

2
@Stephanie, NicoleHamilton : en.wikipedia.org/wiki/Lrzip#Lrzip이 있습니다.
기계 달팽이

1
@Guido 물론 스트림에서 기억하지 못하는 무언가의 중복을 제거 할 수는 없지만 xz -9 -M 95%, 또는 같은 것을 시도하십시오 xz -M 95% --lzma2=preset=9,dict=1610612736. 빠르지는 않지만 결과에 중복이 남지 않을 것입니다.
Eroen

39

Nicole Hamiltongzip 은 사전 크기가 작기 때문에 먼 중복 데이터를 찾을 수 없다는 것을 올바르게 지적 합니다 .

bzip2 900KB의 메모리로 제한되어 있기 때문에 비슷합니다.

대신 다음을 시도하십시오.

LZMA / LZMA2 알고리즘 ( xz, 7z)

LZMA 알고리즘은 Deflate와 동일한 제품군에 있지만 훨씬 더 큰 사전 크기를 사용합니다 (사용자 정의 가능, 기본값은 384MB 임). xz최신 Linux 배포판에 기본적으로 설치되어야하는 이 유틸리티 gzip는 LZMA와 유사 하며 사용합니다.

LZMA는 더 긴 범위의 중복성을 감지하므로 여기에서 데이터를 중복 제거 할 수 있습니다. 그러나 Gzip보다 느립니다.

또 다른 옵션은 (7-ZIP입니다 7z에서, p7zip(LZMA의 저자에 의해 쓰여진) 기본적으로 LZMA를 사용 (오히려 단일 스트림 압축기에 비해)는 아카이버 인 패키지). 7-zip 아카이버는 해당 .7z형식으로 아카이브 할 때 파일 레벨에서 동일한 확장자를 가진 파일을보고 자체 중복 제거를 실행 합니다. 당신이 대체 할 의향이 있다면이 방법은 tar함께 7z, 당신은 중복 제거 동일한 파일을 얻을. 그러나 7z는 나노초 타임 스탬프, 권한 또는 xattrs를 유지하지 않으므로 필요에 맞지 않을 수 있습니다.

lrzip

lrzipGzip / Deflate, bzip2, lzop 또는 LZMA와 같은 일반적인 알고리즘에 데이터를 공급하기 전에 장거리 중복성을 제거하기 위해 데이터를 전처리하는 압축기입니다. 여기에 제공 한 샘플 데이터에는 필요하지 않습니다. 입력 데이터가 메모리에 들어갈 수있는 것보다 큰 경우에 유용합니다.

이러한 종류의 데이터를 들어, 사용한다 (비압축성 덩어리를 중복) lzop과 압축 (매우 빠르게) lrzip가 중복 제거 된 된 후에는 완전히 임의의 데이터를 압축하기 위해 더 열심히 노력하여 얻을 수있는 이점이 없기 때문에.

Bup and Obnam

당신이 질문 태그 때문에 여기에 귀하의 목표는 데이터를 백업하는 경우, 같은 중복 제거 백업 프로그램 사용을 고려 BUP 또는 Obnam을 .


이 lrzip은 흥미로워 보입니다. 비 전통적인 솔루션으로 알려진 저자도 있습니다. 이제 백업 스크립트를 수정해야합니다. 다시.
Eroen

3
+1와, 지식과 경험의 분수입니다. 감사합니다. 중복 제거 가능 파일 시스템을 믹스에 추가 할 수 있습니까? ZFS (그리고 나는 Btrfs가 그것을 가질 예정이라고 생각한다)-블록 정렬 복제와 함께 작동 할 것이다
sehe

LZMA2 압축을 사용하는 7Zip과 1536Mb 표시 크기 (Windows GUI에서 사용 가능한 최대 크기)가 제게 효과적입니다!
Leopoldo Sanczyk

2

지연된 작은 파일 집합이있는 백업의 경우 타르의 파일을 확장명으로 정렬하는 것이 좋습니다.

find archive_dir -type f | rev | sort | rev | tar czf my_archive.tar.gz -I -

나는 모든를 잘라 버리고 rev(왜 뒤집고 정렬 하시겠습니까?) sort옵션 "-r, --reverse"를 보았습니다 (왜 당신이 뒤집기를 원할지는 모르겠습니다). 그러나 나는 당신의 생각 tar옵션 " -I"당신이하지 생각하지 않는다 " -I, --use-compress-program PROG" , 당신은 아마 원하는 "-T를 --files-에서 FILE"
Xen2050

나는이 생각 | tar czf my_archive.tar.gz -I -해야| xargs tar Azf my_archive.tar.gz
올리비에 Dulac

@ Xen2050 rev은 스트림의 행 순서가 아니라 각 행의 문자 순서를 반대로 바꿉니다. 이로 인해 sort파일을 확장자별로 그룹화합니다. stdin에 파일 목록을 제공 하는 -I -should이어야합니다 -T -.
billyjmc

@billyjmc 나는 rev리눅스에 많은 확장이 있다는 것이 아니라 확장에 의해 정렬되는 것을 알았 습니다. 크기별로 정렬하면
Dup

2

gzipxz사전 크기가 크 더라도 복제본을 찾지 못합니다. 당신이 할 수있는 일은 사용입니다 mksquashfs-이것은 실제로 복제 공간을 절약 할 것입니다.

3 개의 랜덤 이진 파일 (64MB)을 사용 xz하거나 mksquashfs사용하는 빠른 테스트 결과 :

설정:

mkdir test
cd test
dd if=/dev/urandom of=test1.bin count=64k bs=1k
dd if=/dev/urandom of=test2.bin count=64k bs=1k
cp test{2,3}.bin
cd ..

스쿼시 :

mksquashfs test/ test.squash
> test.squash - 129M

xz :

XZ_OPT='-v --memlimit-compress=6G --memlimit-decompress=512M --lzma2=preset=9e,dict=512M --extreme -T4 ' tar -cJvf test.tar.xz test/
> test.tar.xz - 193M

mksquashfs는 파일 수준에서 중복 항목 만 찾습니까, 아니면 작은 청크에서도 작동합니까? 즉, 약간 다른 파일이지만 대부분 동일한 파일을 압축합니까?
Chaos_99

이것은 파일 기반에서만 작동합니다. 이 세 가지 테스트 파일을 압축되지 않은 tar 아카이브로 tar하고 mksquashfs를 사용하여 압축 할 때 알 수 있습니다. 반면에, Number of duplicate files foundstdout에서 중복을 발견하면 mksqashfs가보고 합니다.
Izzy

1

내 시스템 lzma test.tar에서 106'3175 바이트 (1.1M) test.tar.lzma 파일이 생성됩니다.


1

'기계적 달팽이'의 답변 외에도

압축되지 않은 단일 파일의 파일 크기 (보다 정확하게는 복제본 간의 거리)가 사전 크기를 초과하면 xz (또는 lzma)조차도 중복을 찾지 않습니다. 가장 높은 설정에서도 xz (또는 lzma)는 -9e64MB 만 예약합니다.

운좋게도 옵션을 사용하여 자신의 디지털 크기를 지정할 수 있습니다 --lzma2=dict=256MB ( --lzma1=dict=256MB명령에 lzma 별명을 사용할 때만 허용됨)

불행히도, 위의 예와 같이 사용자 지정 압축 체인으로 설정을 재정의하는 경우 다른 모든 매개 변수의 기본값은 -9e와 같은 수준으로 설정되지 않습니다. 따라서 압축 밀도는 단일 파일에 비해 높지 않습니다.


-2

명령 행 스위치가없는 gzip은 압축에 가장 낮은 알고리즘을 사용합니다.

다음을 사용하십시오.

gzip -9 test.tar

더 나은 결과를 얻을 수 있습니다


1
실제로는 차이가 최소화됩니다. 나는 비슷한 결과로 bzip2를 시도했다.
귀도

명령 행 스위치가없는 gzip은 압축에 가장 낮은 알고리즘을 사용합니다. => 이것은 사실이 아닙니다- "man gzip"은 "(t) 기본 압축 수준은 -6입니다 (즉, 속도를 희생하여 높은 압축률로 바이어스 됨"). 컴파일 된 기본 설정이 GZIP 환경 변수로 재정의되지 않으면 내가 아는 모든 gzip 버전에 해당됩니다. 주어진 답변에서 이미 설명한 것처럼 수준 "-9"조차도 여기에 도움이되지 않습니다.
Gunter Ohrner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.