为什么 Gzip 压缩不能消除重复的数据块?

Gui*_*ido 31 linux compression gzip

我只是做了一个小实验,我创建了一个包含重复文件的 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
$ 
Run Code Online (Sandbox Code Playgroud)

首先,我创建了一个 1MiB 的随机数据文件 (a)。然后我将它复制到文件 b 并将其链接到 c。在创建 tarball 时,tar 显然知道硬链接,因为 tarball 只有 ~2MiB 而不是 ~3Mib。

现在我希望 gzip 将 tarball 的大小减小到 ~1MiB,因为 a 和 b 是重复的,并且在 tarball 中应该有 1MiB 的连续数据重复,但这并没有发生。

为什么是这样?在这些情况下,我如何有效地压缩 tarball?

Mec*_*ail 39

Nicole Hamilton 正确地指出gzip由于其字典大小较小,因此不会找到远处的重复数据。

bzip2 类似,因为它的内存限制为 900 KB。

相反,请尝试:

LZMA/LZMA2 算法 ( xz, 7z)

LZMA 算法与 Deflate 属于同一家族,但使用更大的字典大小(可定制;默认为 384 MB)。该xz实用程序应默认安装在最新的 Linux 发行版中,类似于gzip并使用 LZMA。

当 LZMA 检测到远程冗余时,它将能够在此处对您的数据进行重复数据删除。但是,它比 Gzip 慢。

另一种选择是7-拉链(7zp7zip包),这是一个存档器(而不是单流压缩机),默认情况下(由LZMA的作者撰写)使用LZMA。7-zip 归档程序在归档为其.7z格式时在文件级别运行自己的重复数据删除(查看具有相同扩展名的文件)。这意味着,如果您愿意替换tar7z,您将获得重复数据删除的相同文件。但是,7z 不保留纳秒时间戳、权限或 xattrs,因此它可能不适合您的需求。

lrzip

lrzip是一种压缩器,用于在将数据提供给 Gzip/Deflate、bzip2、lzop 或 LZMA 等传统算法之前对数据进行预处理以去除长距离冗余。对于您在此处提供的示例数据,没有必要;当输入数据大于内存中可以容纳的数据时,它很有用。

对于这种类型的数据(重复的不可压缩块),您应该使用lzop压缩(非常快)和lrzip,因为在删除重复数据后更努力地压缩完全随机的数据没有任何好处。

Bup 和 Obnam

由于您标记了问题,如果您在这里的目标是备份数据,请考虑使用重复数据删除备份程序,如BupObnam

  • +1 哇,那里真是知识/经验的源泉。赞赏。我可以添加启用重复数据删除的文件系统吗?ZFS(并且,我认为 Btrfs 计划拥有它)- 可以与块对齐复制一起使用 (3认同)

Nic*_*ton 25

Gzip gzip 基于 DEFLATE 算法,它是 LZ77 和 Huffman 编码的组合。它是一种无损数据压缩算法,它的工作原理是使用动态构建的字典将输入流转换为压缩符号并观察重复项。但它找不到分隔超过 32K 的重复项。期望它发现相距 1MB 的重复项是不现实的。

  • @斯蒂芬妮,妮可汉密尔顿:有 https://en.wikipedia.org/wiki/Lrzip#Lrzip。 (2认同)