chunkSizeBytes必须在新建GridFSBucket时指定,无法修改已存文件;机械硬盘推荐设为1MB~4MB以减少寻道,小文件应改用BinData存储。

chunkSizeBytes 参数必须在新建 bucket 时指定
GridFS 的 chunkSizeBytes 是只读元数据,一旦文件写入,就无法修改。试图直接更新 fs.files 中的 chunkSize 字段或 patch fs.chunks 文档,驱动和服务器均不识别,后续读取会失败或返回损坏数据。
- 新建 bucket 时通过选项传入:
new GridFSBucket(db, { chunkSizeBytes: 4 * 1024 * 1024 }) - 已有数据必须重新上传才能生效——不是“迁移”,而是
openDownloadStream()读出、再用新 bucket 的openUploadStream()写入 - 不同业务场景可共用一个数据库,但需用不同
bucketName隔离,避免混用不同块大小的文件
机械硬盘上 chunkSizeBytes 设为 1MB~4MB 更合理
默认 256KB 在机械硬盘(HDD)上引发严重随机寻道:10MB 文件要读 40+ 次,磁头反复移动拖慢整体吞吐。实测 4MB 是多数大文件场景的较优平衡点。
- 设为
4 * 1024 * 1024后,10MB 文件仅需约 3 次寻道,I/O 等待显著下降 - 内存占用略有上升(流式读缓存更大 chunk),但对 HDD 是正向权衡
- 若平均文件小于 1MB,可折中选
1024 * 1024(1MB),避免小文件浪费空间 - 切勿设 >8MB:单次读失败风险高,且部分驱动在流式读时 buffer 分配可能触发 GC 压力
小文件别硬塞 GridFS,CPU 和 I/O 都吃亏
GridFS 天然不适合存储 KB 级文件(如图标、token、JSON 配置)。它强制分块、维护两套索引、触发多次 BSON 解析,CPU 占用异常高,HDD 上读写反而比普通集合还慢。
- ≤10KB 的内容,直接存进普通 collection,字段用
BinData类型(如BinData(0, base64str)) - 确认是否真需要 GridFS:只有 ≥1MB 且不频繁变更的二进制流(PDF、视频片段、导出报表)才适合
- 混合场景下,应用层做路由:文件大小
size → 普通 collection;否则 → GridFS bucket
避免两次查询,优先用 openDownloadStreamByName
常见反模式是先 files.find({ filename: "x.pdf" }) 拿 _id,再 openDownloadStream(id) —— 这触发两次独立磁盘寻道,在 HDD 上代价极高。
- MongoDB 4.4+ 支持
bucket.openDownloadStreamByName("x.pdf"),底层合并元数据查询与首个 chunk 读取,省一次寻道 - 若需额外元数据(如
contentType或自定义metadata),用bucket.find({ filename: "x.pdf" }).next()拿完整GridFSFile,再传给openDownloadStream() - 别在循环里反复
new GridFSBucket:实例复用能保住内部连接池和 chunk 缓存,HDD 初始化延迟比 SSD 明显得多
实际调优时最易被忽略的点是:chunkSize 修改后,必须同步检查 fs.chunks 是否有对应复合索引 { files_id: 1, n: 1 }。缺失该索引时,哪怕 chunk 调大了,读取仍会全表扫描 chunks 集合,性能不升反降。











