ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

移动硬盘/PSSD占用空间远大于文件大小:簇大小与exFAT小文件浪费排查

移动硬盘/PSSD占用空间远大于文件大小:簇大小与exFAT小文件浪费排查 上周把一块用了半年的 1TB PSSD 接上台式机右键属性弹出的对话框让我愣了几秒大小 11.8 GB占用空间 94.3 GB。差了整整八倍。第一反应是硬盘坏了chkdsk 跑完一句错都没报SMART 也是全绿。后来才想明白这不是故障是文件系统在按格子收费而我恰好往这块盘里塞了几十万个小文件。移动硬盘和 PSSD 上文件占用空间远大于文件大小这件事几乎每个把手机备份、代码仓库、素材库往移动盘里搬的人都撞上过。它跟硬盘品牌无关跟是不是固态无关甚至跟你的文件有没有损坏也无关。它取决于三件事文件系统的簇大小、你手上这批文件的平均体积、以及这块盘上有没有藏着回收站、索引、备份残留这类看不见但占地方的东西。这篇就把这三件事拆开讲清楚顺手给出可复现的排查命令和几条能真正省下空间的处置方案不管你是刚买盘的新手还是已经跟存储打了几年交道的运维都能直接拿去用。1. 先把概念钉死属性对话框那两行数字到底谁给的1.1 大小是内容长度占用空间是实际扣减Windows 资源管理器属性里那两行来源完全不同。大小来自文件的逻辑长度字段就是文件里到底有多少字节内容拷贝一个 1234 字节的文本文件过去它永远显示 1234 字节跟存在哪种硬盘上、哪种文件系统上都无关。占用空间则是文件系统实际从卷里划走了多少容量这个数字是由分配粒度决定的是向上取整的结果。打个比方大小是你这趟要搬走的家具总体积占用空间是搬家公司实际派了几辆车。规矩是一辆车装不下就再派一辆且不允许拼车那么一个 1.2 立方米的沙发就可能独占一辆载重 8 立方米的车。你搬了 100 个这样的沙发家具总量才 120 立方米账单上却写着 800 立方米的车位费。文件系统干的就是这个事。理解这一点很关键因为它解释了为什么占用空间总是大于等于大小以及为什么当文件普遍很小的时候两者的比例会失控。同时它也解释了一个反直觉的现象同一个文件从 NTFS 卷复制到 exFAT 卷大小那一栏一个字节都不会变占用空间那一栏可能翻十几倍。1.2 簇是怎么来的为什么它必须是固定大小文件系统要管理一块容量巨大的盘不可能给每个文件单独记账到字节级。它把整个卷切成等大的方块这就是簇Cluster也叫分配单元Allocation Unit。一个簇要么完整地属于某个文件要么完全空闲没有中间状态。为什么不做成 1 字节一个单位因为那样记账表本身会大得离谱。假设 1TB 的盘按 1 字节分块光是记录每块归属的表格就要 1TB 以上比数据本身还大。固定大小的簇是一种工程妥协块越大管理表越小、读取越连续但小文件的浪费越严重块越小空间利用率越高但管理表膨胀、寻址变慢。这里有个很多人忽略的点簇大小是格式化时写死在卷结构里的之后所有文件的分配都按它来算。它不是一个可以随时调整的软参数想改只能重新格式化这一点后面会专门讲。1.3 为什么这个差距偏偏在 PSSD 上被放大得特别明显如果同样的文件放在系统盘上你可能根本注意不到这个问题。原因是 Windows 对 NTFS 卷的默认簇大小是4 KB——即使卷容量达到 16TBNTFS 默认也还是 4 KB。4 KB 的格子装一个 3 KB 的文件浪费 1 KB比例上是 33%疼但不致命。但移动硬盘出厂预格式化的绝大多数是 exFAT而 Windows 对 exFAT 的默认分配单元大小是按容量分档给的32GB 以上的卷动辄 32 KB256GB 以上直接给128 KB1TB、2TB 的盘基本都是这个数。PSSD 起步就是 1TB所以绝大多数人拿到手的那块盘格子就是 128 KB 见方。再叠加一层现实会用移动硬盘的人装的往往不是电影这种大文件而是手机备份、照片缩略图、聊天记录附件、源码仓库、设计素材——这些恰恰由海量小文件构成。大格子配小文件这就是差距被放大的根本原因。1TB 的 PSSD 出厂状态可以说是最不适合装小文件的配置之一。2. 自己动手算一遍簇浪费究竟能有多大2.1 一条够用的估算公式不需要精确到字节一条粗略但足够判断严重程度的公式是占用空间 ≈ Σ ceil(文件大小 / 簇大小) × 簇大小当文件体积远小于簇大小时ceil的结果几乎恒等于 1公式退化成占用空间 ≈ 文件数量 × 簇大小这时候平均每个文件的浪费接近簇大小的一半。也就是说一块 128 KB 簇的盘装 10 万个平均 8 KB 的文件实际内容才 800 MB账面占用却是 10 万 × 128 KB 12.8 GB放大 16 倍。这条公式还给了你一个快速判断的抓手只要文件数乘以簇大小接近你看到的占用空间问题就基本落在簇浪费上不用再往坏道、病毒那个方向查了。反过来如果算出来的数字远小于实际占用那说明还有别的元凶在吃空间得走后面的排查链路。2.2 三种典型文件分布的浪费对照拿一块 1TB 的盘举例同样是 60 GB 的实际内容不同的文件构成会得到完全不同的账面占用。下面这组数字是我按上面公式实算的可以直接对照自己的盘看文件构成平均文件大小文件数128KB 簇下占用4KB 簇下占用放大倍数128KB少量大文件视频素材800 MB7560 GB60 GB约 1.0混合负载照片 文档300 KB20 万25.6 GB60 GB无放大碎片化负载手机备份、缩略图6 KB1000 万巨大约 62 GB数十倍极端小文件源码、配置、日志碎片1.5 KB400 万512 GB约 61 GB数百倍第三、四行那种情况128 KB 簇下占用会直接顶到盘的物理容量上限附近甚至出现明明没几个 G 的内容盘就满了的观感。这类场景在把 iPhone 备份、IDEA 工程目录、或者大量网页素材往移动盘里搬的时候特别常见。顺带说一个对照同一批文件放在 NTFS 4 KB 簇上占用空间基本贴着实际内容走最多多个百分之几。所以如果你从系统盘往移动盘拷同一批文件发现占用空间突然暴涨那不是拷贝出错是目的卷的格子变大了。2.3 量出你手上这块盘的真实簇大小别再靠猜。Windows 上最干净的一条命令是查Win32_Volume的BlockSize属性它直接就是分配单元大小Get-CimInstance -ClassName Win32_Volume | Where-Object { $_.DriveLetter -eq E: } | Select-Object DriveLetter, FileSystem, BlockSize, Capacity把E:换成你的盘符即可。BlockSize那一栏是 131072就是 128 KB是 4096就是 4 KB。另一条同样安全的只读命令是chkdsk E:不加/f不会改动任何东西它会在输出里打印每个分配单元中的字节数。macOS 和 Linux 上可以用stat直接看单个文件在实际磁盘上占了多少块这是最直观的验证方式# macOS / Linux 通用%z 是大小%b 是占用块数512 字节为单位 stat -f %N size%z blocks%b actual%b*512 ./某个小文件macOS 上更推荐用diskutil info /Volumes/你的盘名在输出里找Allocation Block SizeLinux 上装好 exfatprogs 后用mkfs.exfat -n之类的探查参数或者直接看某目录下所有文件的blocks总和与实际大小之比。批量的、图形化的方案我更推荐 WizTree 和 TreeSize两者都能直接显示 Size on disk 这一列可以按占用空间排序一眼就能看出哪个目录是重灾区。3. 除了簇浪费还有几批隐形的占位者3.1 iPhone 备份落到 exFAT 上硬链接会被展开这是移动硬盘空间被莫名其妙吃掉最常见的原因没有之一。iPhone 备份目录里的文件是用哈希字符串命名的散装文件靠一个 SQLite 数据库做索引中间会大量使用硬链接——同一份数据被多个文件名同时引用在支持硬链接的文件系统上只占一份物理空间。问题在于exFAT 和 FAT32都不支持硬链接。在 macOS 上用 Finder 做出来的备份一旦原样拷进 exFAT 卷所有硬链接关系会被展开成一个个独立的物理副本占用空间瞬间成倍增长。更麻烦的是这类备份目录本身就有几十万个文件再叠加 128 KB 的簇账面占用可以轻松膨胀到实际内容的好几倍。Windows 上通过 Apple 设备应用改备份路径到移动盘的时候同样会遇到小文件海量堆积的问题。区别在于 Windows 版备份创建硬链接的方式不同但只要落点是 exFAT就等于主动放弃了所有共享存储的可能性所有去重效果归零。3.2 macOS 在非原生卷上撒的那些小文件一块盘只要被 mac 插过一次往往就会多出这些东西.Spotlight-V100Spotlight 索引数据库扫描越充分体积越大几十 MB 到几 GB 都见过。.fseventsd文件系统事件日志记录磁盘上发生过哪些变更。.Trashesmac 下的回收站删了东西不等于释放。.DS_Store每个目录一个记录文件夹的显示排列方式。._xxx文件AppleDouble在非原生卷上mac 会把原本存在扩展属性里的元数据写成同名的独立小文件。这类文件通常只有一个簇那么大一个目录下几百个文件就凭空多出几百个 128 KB 的占用。这几种加起来在几百万小文件的场景下能吃掉意想不到的容量。而且它们带点号开头在 Windows 资源管理器里默认是可见的因为 exFAT 上不属于隐藏属性但在 mac 上默认不显示来回切换系统的人很容易漏看。3.3 回收站、卷影副本与文件系统自身的账本Windows 在这块盘上也会留下自己的痕迹。$RECYCLE.BIN是你的回收站删进去的文件仍在占用空间System Volume Information里如果开了卷影副本或者系统保护会保存历史版本容量可能相当可观。这两个目录在资源管理器里默认不显示需要打开显示隐藏文件并取消隐藏受保护的操作系统文件才能看到。文件系统自己的账本也要占地方。NTFS 的$MFT记录每一条文件元数据一条记录 1 KB 起步上百万个文件就是上 GB$Bitmap按位记录簇的占用情况。exFAT 的结构更直接FAT 表每个簇一项、每项 4 字节再加一份分配位图每个簇 1 位。1TB 的盘用 128 KB 簇时FAT 表约 32 MB看着不多等你在后面看到把簇改小的方案时会发现这个数字会反过来咬你一口。3.4 反过来的情况占用空间比大小还小也有一批场景是占用空间小于大小遇到了别慌同样正常NTFS 压缩属性文件被压缩存储逻辑大小不变实际占用变小。注意这个属性只在 NTFS 上有效拷到 exFAT 就自动失效并还原成完整大小。稀疏文件文件里那些全零的区域不实际分配簇。动态扩展的虚拟磁盘镜像VHDX、qcow2和数据库预分配文件是重灾区一个显示 100 GB 的镜像文件可能只占总 5 GB。硬链接和 APFS 克隆多个文件名指向同一份数据你在某一处统计它的大小时会重复计数但占用空间只算一次。这也解释了一个经典疑问把一块盘上的目录整个拷贝到另一块盘为什么两边统计出来的数字对不上。元数据、链接关系、压缩属性都可能发生变化占用空间自然会变。4. 完整的排查链路从差这么多到锁定具体元凶4.1 第一步做整卷的收支表先分清是哪一类问题先别急着翻目录。打开此电脑看整块盘的容量、已用、可用再和底层工具给的数字对一下。如果已用空间和所有文件占用空间之和差得离谱说明有大量隐藏或不可见的东西在占地方优先查 3.2 和 3.3 那几类。如果两者接近但占用空间之和和大小之和差距巨大那就是典型的簇浪费走 4.2 的路径。这一步的意义在于把问题分流。很多人一上来就找哪个大文件占了空间结果忙活半天其实元凶是几十万个几百字节的小文件加 128 KB 的簇方向一开始就错了。4.2 第二步按目录排序圈出小文件重灾区用 WizTree读 NTFS 的 MFT速度极快对 exFAT 走遍历稍微慢一点但可接受或者 TreeSize打开目标盘先按占用空间降序排列然后展开占比最大的那几层目录。你会看到一个很典型的现象某个目录下文件数几十万、平均体积几 KB占用空间却是实际大小的几十倍。这一步建议同时看两个指标文件数量和占用空间。占用空间大但文件数少的通常是正常的视频大文件占用空间中等但文件数惊人的才是要处理的。iPhone 备份目录、.git目录、node_modules、缩略图缓存目录是四个高频命中点。4.3 第三步抽样验证把单个文件的账算清楚锁定嫌疑目录之后从里面抽几个文件做单点验证。Windows 上右键属性看两行数字或者用 Sysinternals 的du直接输出磁盘占用du -u -v E:\MobileSync\Backup\某目录\某文件macOS / Linux 上用前面那条stat命令把blocks乘 512 得到实际占用和size一比就能算出单个文件的放大倍数。抽十来个样本心里就有数了。注意抽查的时候一定要抽小文件。随手点一个几百 MB 的视频文件会发现它占用空间几乎等于大小很容易得出没问题的错误结论。问题的根源永远在那些你一眼扫过去的碎片文件上。4.4 第四步把隐藏目录和保留区单独算一遍打开显示隐藏文件和系统文件的选项重新对根目录做一次统计。重点看$RECYCLE.BIN、System Volume Information、.Trashes、.Spotlight-V100、.fseventsd。这些目录能被扫描工具统计到但常规的选中所有文件看属性的操作会漏掉一部分。还有一个容易被忘掉的地方分区表本身和对齐留白。有些出厂盘会在前面留一段未分配区域或者存在隐含的恢复分区。这部分容量在此电脑里看不到但确实占着盘。用磁盘管理工具Windows 的 diskmgmt.msc 或 mac 的磁盘工具看一下分区布局能排除掉这类干扰。5. 四条可落地的处理路径以及各自要付的代价5.1 重新格式化把簇改小怎么选怎么操作最彻底的方案是重新格式化把分配单元大小降下来。但前提是数据必须已经备份到别处格式化是不可逆操作别指望中途反悔。选多大的簇要看用途。给几个我实际用下来比较稳的档位纯文档、源码、小文件为主NTFS 用 4 KBexFAT 用 4 KB 到 8 KB。空间利用率最高。混合负载照片、视频、少数大文件NTFS 4 KBexFAT 32 KB 是比较均衡的选择。纯大文件视频素材、镜像仓库exFAT 128 KB 反而更合适顺序读写表现更好元数据开销也小。但这里有一个必须讲清楚的权衡exFAT 是 FAT 链表结构簇越小FAT 表越大。1TB 的盘用 128 KB 簇FAT 表约 32 MB改成 4 KB 簇簇数涨到 2.68 亿FAT 表直接变成 1 GB 量级可能还有备份副本分配位图也要 33 MB。也就是说你在文件上省下来的空间有一部分会被元数据吃掉。NTFS 没有这个包袱因为它是 B 树索引结构不依赖链表这也是为什么 NTFS 敢在 1TB 上默认 4 KB。三平台的操作命令:: Windows 命令行格式化X 换成实际盘符务必确认盘符没错 format X: /FS:exFAT /A:32K /Q :: 或者用 PowerShell Format-Volume -DriveLetter X -FileSystem exFAT -AllocationUnitSize 32768 -Confirm:$false# Linux需要 exfatprogs sudo mkfs.exfat -c 32K -L MyDisk /dev/sdX1 # NTFS 则用 sudo mkfs.ntfs -c 4096 -L MyDisk /dev/sdX1macOS 上图形化的磁盘工具在新版系统里已经不再暴露块大小选项需要走命令行# 先卸载卷再用 newfs_exfat 指定块大小最后挂载 diskutil unmount /dev/diskXsY sudo newfs_exfat -b 32768 -v MyDisk /dev/rdiskXsY diskutil mount /dev/diskXsY提示格式化前把盘符、设备名都核对两遍。mkfs和newfs系列命令不会问你确定吗写错设备名就是直接抹掉另一块盘的数据这种事故我见过不止一次。5.2 打包成单一大文件不压缩容器的思路如果这批小文件你需要长期放在移动盘上又不常单独读取还有一个绕开簇大小的办法把它们打包成一个或几个大文件。这样文件系统只需要给这个大文件分配连续空间格子浪费的问题基本消失。关键是别用默认压缩。高压缩比格式比如最高档的 7z在面对照片、视频这类已压缩数据时压缩收益接近零反而会慢到无法忍受。正确的做法是用仅存储模式打包# 创建一个不压缩的 tar纯打包 tar -cf photos.tar /path/to/photos # 7-Zip 的仅存储模式速度极快 7z a -mx0 backup.7z ./somedir # Windows 下也可以直接做成 VHDX 容器文件当普通磁盘挂载使用用 tar 或者-mx0的原因很直接打包这个动作的价值在于把几十万个小文件变成几个大文件压缩是额外收益不是目的。真需要压缩的场合比如纯文本源码单独拿出来压就好。代价是访问不方便你需要先解开才能读单个文件所以这个方法更适合归档型数据。5.3 按用途分卷选格式mac、Windows、Linux 共存的取舍如果你需要在 mac、Windows、Linux 三边都能读写格式选择本身就很难两全。把常见选项摊开看格式三平台读写默认簇大小大容量硬链接日志单文件上限exFAT原生支持128 KB不支持无16 EBNTFSWin 原生mac/Linux 需额外支持4 KB支持有16 TB 量级FAT32全支持16-32 KB不支持无4 GBAPFS / HFS仅 mac 原生4 KB支持有很大三平台通吃的现实答案基本就是 exFAT代价就是你得接受它的默认大簇和没有日志。所以我更推荐另一种思路按数据用途分卷而不是按格式强求统一。一块盘分两个区一个 exFAT 放需要跨平台交换的文件一个 NTFS 或 APFS 放只在单一系统里用的大批量小文件各取所需。顺便说一句单文件上限的事它比想象的更细碎FAT32 卡在 4 GB这是很多人往老 U 盘拷大镜像时踩的坑与此同理服务端也有自己的一套上限阈值比如应用框架里配置的单文件提交上限、反向代理层配置的请求体大小限制两边任何一边没对齐都会表现为文件传不上去而不是报错。本地操作和网络传输虽然场景不同但道理都是上限写在配置里不对齐就出问题。5.4 什么时候该认命不值得优化的场景不是所有情况都值得折腾。如果你的盘主要装视频素材、虚拟机镜像、大型安装包平均文件体积在几十 MB 以上那么 128 KB 的簇带来的浪费可以忽略重格式化的收益还抵不上操作风险。同理如果你只是临时拷一批文件过去用完就删也没必要为了这几天的占用空间重做卷。判断标准很简单先算一下占用空间 ÷ 实际内容大小这个比值。低于 1.2别管它1.2 到 3 之间看你耐心超过 5 且打算长期这么用才值得动格式化这把刀。6. 几个我踩过的坑和顺手记下的经验6.1 改簇大小只能重建不存在就地调整我最早天真地以为这类操作有类似碎片整理的调整工具结果找了半天能改簇大小的工具无一例外都是先导出数据、重建卷、再导回。原因在 2.1 讲过簇大小写在卷结构里卷上所有文件的分配记录都是按它算的就地改等于把整本账撕了重记。所以正确流程只有一条把数据完整拷到另一块盘格式化目标盘再把数据拷回来。这里有个细节如果源数据就在这块要格式化的盘上那必须找第三块盘做中转。用移动硬盘中转的时候中转盘最好是 NTFS 或 APFS别再用 exFAT否则中途的拷贝过程又会把簇浪费叠一层。6.2 exFAT 没有日志掉盘一次代价很大exFAT 至今没有日志机制这意味着写入过程中如果断电、拔线、系统崩溃文件系统的元数据可能处于不一致状态。表现出来就是卷变成拒绝访问或者提示需要格式化。我个人养成的习惯是拔盘前一定先安全弹出哪怕只是拷了几个文件。Windows 上可以用安全删除硬件mac 上用diskutil ejectLinux 上用udisksctl unmount再断电。另一个习惯是不用 exFAT 卷直接编辑大文件编辑类操作比如剪辑、数据库产生大量非顺序写入掉盘风险高得多这类活儿还是放在 NTFS 卷上做。6.3 把移动硬盘当系统盘、往里放分页文件有个常见的省空间思路是把系统分页文件挪到移动硬盘上觉得反正固态快。这事我不建议做理由有三条。第一分页文件被高频随机访问USB 或雷电链路的稳定性远不如板载接口链路一抖动就是直接蓝屏或进程崩溃。第二拔盘的时候分页文件还在被占用系统会阻止你弹出或者更糟——弹出失败但你强行拔了。第三分页文件本身是高度稀疏和动态伸缩的放在 exFAT 上既没有稀疏支持也没有压缩支持空间表现反而更差。如果你的系统盘确实吃紧正确的做法是调整分页文件的总量和分布而不是把它丢到外接盘上。把每块盘的初始大小和最大值都收敛一下别让系统自动管理无限膨胀通常就能腾出几 GB 到几十 GB 不等。6.4 备份永远是第一优先级最后说一个看起来跟空间无关、但实际关系最大的经验。我见过太多人在空间不够的压力下一边格式化一边盼着拷回来的数据别出问题结果中途掉盘两边都没了。合理的做法是任何时候都要有两份能独立存活的副本而不是一份数据加一份正在生成的备份。真要精简精简的做法是删冗余、删缓存、删回收站而不是拿唯一的一份数据去冒险。空间不够的时候先问这些数据哪些是可以不带的再问怎么把它塞得更紧。顺序反了代价往往不是几个 G 的空间而是几年的资料。至于我自己现在的做法小文件密集的归档目录一律打包成不压缩的 tar 放在 NTFS 分区上跨平台交换才用 exFAT 那个区iPhone 备份则单独划一块大区、用对应系统的原生格式从根上避开硬链接展开和簇浪费这两个坑。用了两年多再没出现过大小 11 GB、占用 94 GB这种让人心里一沉的情况。
返回列表