认识
稀疏文件是一种聪明的存储优化技术,它通过区分文件的“逻辑视图”和“物理存储”,巧妙地避免了为空洞数据分配实际空间。它在虚拟化、数据库等需要处理大型文件的领域发挥着至关重要的作用。然而,在使用时也需要了解其特性,避免在管理、备份和传输过程中出现意外。简单来说,稀疏文件是一种计算机文件,它能够高效地存储那些大部分内容为空(通常是连续的零)的文件。
它的核心思想是:“没有必要为那些毫无意义的零值数据实际分配物理磁盘空间。”
当程序创建一个稀疏文件时,文件系统不会立即为整个文件大小分配相应的磁盘块,而是只记录文件的“逻辑大小”和其中包含实际数据的“物理大小”。
- 逻辑大小:是文件看起来的大小,也就是你通过 `ls -l` 或文件属性看到的尺寸。
- 物理大小:是文件实际在磁盘上占用的空间,也就是你通过 `du` 命令看到的尺寸。
对于稀疏文件,逻辑大小 >> 物理大小。
组成
技术原理
当应用程序尝试在文件中创建一个“空洞”时(例如,使用 `lseek` 然后写入),文件系统不会向后分配磁盘块,而是:
- 在文件的元数据中记录这个区域是“未分配”的。
- 当后续有读取操作访问这个“空洞”区域时,文件系统会动态地返回零值,而无需从磁盘读取任何数据。
- 只有当应用程序真正向“空洞”的某个部分写入非零数据时,文件系统才会为那个特定的数据块分配物理磁盘空间。
文件创建
与常规文件的创建方式不同,当创建 Sparse File 时:
1、不会将组成块的实际字节写入磁盘,
2、而是,在元数据中,记录文件大小,并将元数据写入磁盘。
3、当向文件写入数据时,才会分配实际的数据块。
4、当读取稀疏文件时,文件系统透明地将表示空块的元数据转换为在运行时填充 NULL 字节的“真实”块;
所以,能否使用 Sparse-File 取决于文件系统是否支持。
/Sparse_File/pasted_image.png)
性质
优点:
- 节省磁盘空间:这是最直接的好处。可以创建远大于可用物理存储空间的文件。
- 提高 I/O 效率:由于不需要读写大量的零,文件操作(如创建、复制)会更快,减少了不必要的磁盘写入。
- 节省内存:当映射稀疏文件到内存时,操作系统只会为实际使用的部分分配物理内存页。
缺点:
- 空间报告混淆:使用 `ls -l` 看到的文件大小具有误导性,可能导致误判磁盘剩余空间。应始终使用 `du` 来检查实际占用空间。
- 处理不当可能导致空间爆满:如果一个稀疏文件被一个不理解稀疏特性的工具处理(例如,某些简单的逐字节复制的工具),它可能会被“实体化”,即所有空洞都被真实的零填充,瞬间占满磁盘空间。
- 碎片化:如果不断向空洞中随机写入数据,文件的实际数据块可能会在磁盘上变得非常分散,影响读取性能。
- 备份和传输的复杂性:备份工具(如 `tar`, `rsync`)需要支持稀疏文件特性(如 `tar -S`, `rsync -S`),才能高效地传输它们,否则会在目标端创建充满 0 的实体文件。
构建
在 Linux/Unix 中
使用 `dd` 命令,这是最经典的创建方法。
dd count=0 bs=1M seek=100 of=/path/to/myfile # 创建一个 1GB 大小,但内容全是“空洞”的文件 dd if=/dev/zero of=sparse_file.img bs=1 count=0 seek=1G # `if=/dev/zero`:输入源,一个无限输出零的设备。 # `of=sparse_file.img`:输出文件。 # `bs=1`:块大小设为 1 字节(为了兼容性)。 # `count=0`:不从输入源复制任何块。 # `seek=1G`:在输出文件中跳过 1GB 的位置再开始写。这个“跳过”的区域就形成了空洞。
稀疏文件的实际大小
- So what is the size of that file? Sparse Files on Linux
- unix – what is the most reliable command to find actual size of a file linux – Stack Overflow
ls -lh sparse_file.img # 查看逻辑大小,显示为 1.0G du -h sparse_file.img # 查看物理大小,显示为 0 或 4.0K(仅元数据)
在 Windows 中
Windows 的 NTFS 文件系统也原生支持稀疏文件,但通常通过 API(`DeviceIoControl` 与 `FSCTL_SET_SPARSE`)或在程序中设置文件属性来管理。
在资源管理器中,可以查看文件的“占用空间”和“大小”,其中“占用空间”就是物理大小。
判断稀疏文件
archlinux/Sparse file
Finding sparse files?
# 通过 find 判断文件是否为稀疏文件 # 最左边一列(%S)显示的值是(BLOCK-SIZE * st_blocks / st_size),在稀疏文件的情况下通常小于 1.0 # find /var/lib/libvirt/images f -printf "%S\t%p\n" 0.217076 ./cnicd-02.qcow2 0.152867 ./cnicd-01.qcow2 0.925253 ./ci-node-01.qcow2 1 ./develop.qcow2 0.48236 ./cluster-08.qcow2 0.100322 ./develop-235.qcow2 1 ./develop-354.qcow2 # ls shows the gray+green areas, the logical length of the file. # du (without --apparent-size) shows only the green areas, since those are the ones that take up space. # ls -lh cnicd-01.qcow2 -rw------- 1 libvirt-qemu kvm 101G Mar 30 02:24 cnicd-01.qcow2 # du -h cnicd-01.qcow2 16G cnicd-01.qcow2 # stat -c '%b*%B-%s' -- "$file" # 或使用 stat 命令
复制稀疏文件
方法还是由很多的,性能可能会有所差异,使用场景以有些不一样的地方:「What is fastest way to copy a sparse file? What method results in the smallest file?」
可以使用 cp、dd、cpio、rsync、virt-sparsify 等命令,其中 virt-sparsify 是用于虚拟机迁移,当时是为了迁移虚拟机镜像文件,才有所涉猎。
这里不再深入,有需要的时候再研究,详细内容参考各个命令的手册。
应用
虚拟磁盘映像:VMware、VirtualBox、QEMU/KVM 等虚拟化软件广泛使用稀疏文件来存储虚拟机的硬盘。当你创建一个“动态分配”的 100GB 虚拟磁盘时,最初它可能只占用几 MB 空间,随着虚拟机内数据的增多而逐渐膨胀。
数据库:某些数据库使用稀疏文件来预分配大量的存储空间,以确保其有连续的存储区域,同时又不会一开始就耗尽所有磁盘空间。
日志文件:某些系统会预创建大的日志文件,但一开始并不写入数据。
科学计算:处理大型但稀疏的矩阵或数据集时非常有用。
参考
Wikipedia/Sparse file/https://en.wikipedia.org/wiki/Sparse_file
What is fastest way to copy a sparse file? What method results in the smallest file?
Sparse Files – GeeksforGeeks
How to find all the sparse files in Linux
DeepSeek / 介绍稀疏文件 Sparse File