2026-10-31·by Sijie Wang

small-files

Small files: metadata cost per file, three costs, merge at write time, container formats, HAR, CombineFileInputFormat, and why adding DataNodes does not help.

小文件:元数据账单,和四种少付它的办法

动机就是元数据算术。 账在 block-size-and-metadata-math 里:文件再小,也至少一个文件节点加一块,决定成本的是文件个数,不是数据量。100 万个 1KB 文件的元数据,远多于 1 个 1GB 文件,而数据量只有后者的千分之一。

贵在三处。 第一是内存:NameNode 账本随文件个数长,极端时一台机器根本装不下。第二是启动:FsImage 加载和块报告吸收都随个数变慢。第三是处理:读一个小文件也要走全套流程——问 NameNode、找 DataNode、建连接——这套 overhead 比几 KB 数据本身还大。跑 MapReduce 时,一个小文件起一个 mapper,调度开销比计算还大。

四种少付的办法。 第一,写入端合并:攒一批再写一个大文件,别一个记录一个文件。这是治本,后面三条都是给已经产生的小文件治标。第二,容器格式:SequenceFile、Avro、Parquet 把很多条记录装进一个大文件,记录级可读、可切分,文件个数一下下来,记录访问还在。第三,HAR 归档:Hadoop Archive 把很多小文件打包成几个大文件加索引,读起来透明——但打包后不能改,所以 HAR 只适合冷的、定型的数据。第四,任务时合并 split:CombineFileInputFormat 把很多小 split 合成一个任务,mapper 数下来了,文件本身不用动。

什么帮不上。 加 DataNode 对 NameNode 一点用没有:瓶颈是账本,DataNode 存的是数据,不是账本条目。账本的扩容答案是 federation,而且即使那样也只在小文件摊到多个命名空间时才有用:全堆在一个命名空间里的小文件,照样炸掉那个 NameNode。先合并,再 federation。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →