什么是稀疏文件,为什么我们需要它?

33
什么是稀疏文件,为什么需要它呢?我能想到的就是,它是一个非常大的文件(以基准字节计算),并且它在使用磁盘空间方面非常高效。那么,它为什么高效呢?

据我所了解,如果您有大文件并且包含许多0字节块(例如,使用哈希算法计算存储数据的位置),操作系统将不会分配0字节块,而仅分配所需的数据。我以前从未使用过它,因为我从未有过像我描述的任务。 - nabuchodonossor
0字节的块?请解释一下 @nabuchodonossor - Luv33preet
1
好的,你也可以谷歌一下(Microsoft NTFS稀疏文件),从那里找到解释,但你问了,所以我复制和粘贴一些内容:“一个文件中有许多数据为零时,就称为包含稀疏数据集。这样的文件通常非常大——例如,包含待处理图像数据的文件或高速数据库中的矩阵。包含稀疏数据集的文件的问题在于,大部分文件都不包含有用的数据,并且因此它们是磁盘空间的低效利用...” - nabuchodonossor
2个回答

41

假设你有一个带有许多空字节\x00的文件。这些许多空字节\x00被称为空洞。存储空字节并不高效,因为我们知道文件中有很多这样的字节,那么为什么要将它们存储在存储设备上呢?相反,我们可以存储描述这些零的元数据。当进程读取文件时,这些零字节块会动态生成,而不是存储在物理存储设备上(请查看维基百科上的此示意图):

稀疏文件 - 维基百科

这就是稀疏文件高效的原因,因为它不在磁盘上存储零,而是保存足够的数据描述将要生成的零。

注意: 稀疏文件的逻辑文件大小大于物理文件大小。这是因为我们没有将零物理存储在存储设备上。


编辑:

当您运行:

$ dd if=/dev/zero of=output bs=1G count=4

这里的命令将4G字节的空字节块复制到output。要查看:

$ stat output
File: ouput
  Size: 4294967296      Blocks: 8388616    IO Block: 4096   regular file
--omitted--

你可以看到这个文件已经分配了 8388616 个块,这些块存储的只是从 /dev/zero 复制的 空字节,它们确实占用物理磁盘空间,但它们是存储在磁盘上的空洞(稀疏零)。dd 执行了你所要求的任务,将数据块从一个文件复制到另一个文件。

现在,运行此命令以检测空洞并使文件本身成为空洞文件:

$ fallocate -d output
$ stat output
File: swapfile
  Size: 4294967296      Blocks: 0          IO Block: 4096   regular file
--omitted--

你有注意到什么吗?现在块的数量为0,因为只存储空字节的块已经被释放。记住,output 的块并没有存储任何内容,只有一堆空零,fallocate -d 检测到只包含空零的块并将它们释放了,由于该文件的所有块都包含零,它们都被释放了。

同时注意到大小保持不变。这是文件的逻辑(虚拟)大小,而不是它在磁盘上的大小。重要的是要知道,output 现在不占用任何物理存储空间,它没有分配任何块,因此它实际上不使用磁盘空间。运行 fallocate -d 后保留了大小,所以当您稍后从文件中读取时,您会在运行时获得文件系统生成的空字节。然而,output 的物理大小为零,它不使用任何数据块。

记住,当您读取 output 文件时,文件系统会动态生成空字节,它们实际上没有物理存储在磁盘上,并且 stat 报告的文件大小是逻辑大小,而 output 的物理大小为零。在这种情况下,当进程读取该文件时,文件系统必须生成4G的空字节。

使用dd来生成一个稀疏文件:

$ dd if=/dev/zero of=output2 bs=1G seek=0 count=0
$ stat 
stat output2
  File: output2
  Size: 4294967296      Blocks: 0          IO Block: 4096   regular file

GNU dd内部使用lseekftruncate,因此请查看truncate(2)和lseek(2)。


所以,当我们使用这种方法创建一个文件 sudo dd if=/dev/zero of=/swapfile bs=1G count=4 时,这个文件在磁盘上的大小是零,对吗? - Luv33preet
当你使用 sudo dd if=/dev/zero of=/swapfile bs=1G count=4 命令创建文件时,它在磁盘上不会有零大小。因为 dd 将零字节复制到你的文件中。换句话说,你实际上是将 /dev/zero 中的零字节复制到了 /swapfile 中。然而,这个命令 dd if=/dev/zero of=sparse_file bs=1G seek=4 count=0 创建了一个稀疏文件,你可以在两个文件上运行 stat 命令并查看 Blocks 字段的变化。你的命令是创建交换文件的推荐方式。 - GIZ
1
@Luv33preet 我已经编辑了我的回答。它们是存储在磁盘上的空洞(只是稀疏的零),因此该文件不是稀疏的。稀疏文件通过不在磁盘上存储稀疏零来有效地利用磁盘空间。 - GIZ
1
@direprobs 我尝试编辑您的最后一个示例以匹配您的评论。答案中的文本未按预期工作。但是,该编辑被拒绝了。请批准此编辑或自行进行编辑,我相信这只是复制粘贴错误。 - Evan Benn
很好的解释 - Alex
显示剩余2条评论

10
稀疏文件是指大部分内容为空的文件,即它包含大块值为0(零)的字节。
在磁盘上,文件内容以固定大小的块存储(通常为4 KiB或更大)。当此类块中包含的所有字节都是0时,实现稀疏文件的文件系统不会将该块存储在磁盘上,而是将信息保存在文件元数据某个位置。
使用稀疏文件的优点:
- 数据空块不占用磁盘空间;它们不像正常数据块那样存储,而是将它们的标识符(仅使用几个字节)存储在文件元数据中;这样每个空块就可以节省4 KiB(或更多)的磁盘空间; - 从稀疏文件中读取空块数据不需要时间;因为没有从磁盘读取任何数据,所以这种情况发生;由于文件系统知道块中的所有字节都是0,因此它只将输入缓冲区中的所有字节设置为0,数据就已经准备好了;无需访问缓慢的存储设备; - 向稀疏文件中写入空块数据也不需要时间;在写入时,文件系统检测到块是空的(所有字节均为0),并将块ID放入空块列表(在文件元数据中);没有数据被写入磁盘。
更多关于稀疏文件的信息可以在维基百科页面上找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接