
传统教条:
“数据库是存结构化数据的,文件(图片、PDF、视频)要去存对象存储(AWS S3, OSS)或者硬盘文件系统。数据库里只存路径(/uploads/image.jpg)。”
现实痛点:
BLOB 的逆袭:
SQLite 官方测试表明:对于小于 100KB 的文件,直接读写数据库的 BLOB 字段,比读写文件系统快 35%! 因为它减少了系统调用(syscall)的次数。
1. 核心原理:BLOB 是什么?
BLOB (Binary Large Object) 是数据库中专门用来存储二进制数据(图片、音频、压缩包)的字段类型。
- MySQL: TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
- PostgreSQL: BYTEA
- Oracle: BLOB
当你选择存 BLOB 时,文件不再是散落在磁盘上的碎片,而是数据库页(Page)的一部分。
2. BLOB 逆袭的三大理由
理由一:完美的 ACID 事务支持 (The Killer Feature)
这是 BLOB 最大的杀手锏。
- 文件系统方案: 文件操作和数据库操作是分离的,没有原子性。
- BLOB 方案: 文件就是一行数据。
- BEGIN TRANSACTION
- 插入用户数据
- 插入头像文件 (BLOB)
- COMMIT
- 结果: 要么都成功,要么都失败。永远不会出现“有记录无文件”或“有文件无记录”的数据腐烂问题。
理由二:单文件备份 (Simplified Backup)
想象一下你要迁移服务器。
- 传统方案: 此时你需要用 rsync 同步几百万个小文件(极慢),还要导出 MySQL。
- BLOB 方案: 你只需要 mysqldump 或者拷贝 SQLite 的那个 .db 文件。一个文件带走所有,数据一致性 100% 保证。
理由三:小文件读写性能
现代数据库(如 PostgreSQL 和 SQLite)对变长数据做了深度优化。当文件很小(例如 < 20KB)时,它们通常直接存储在 B+ 树的叶子节点中。读取这行数据时,文件内容已经被加载到 DB Buffer Pool(内存)里了,无需二次 I/O。
3. 实战场景:哪些情况 必须 用 BLOB?
注意,我们不是建议你把 4K 电影存进去。BLOB 适用于 “小、重要、强关联” 的数据。
场景一:用户头像与缩略图 (Small Images)
- 特征: 文件极小(通常 < 50KB),数量极大。
- 优势: 使用 BLOB 存储,Web Server 在查询用户 Profile 时,一次 SQL 就能把“昵称”和“头像数据”一起查出来,直接转 Base64 返回给前端,减少了一次 HTTP 请求或文件 IO。
场景二:关键业务凭证 (Sensitive Contracts)
- 特征: 电子合同 PDF、支付签名证据、医疗检查报告。
- 需求: 强安全性。
- 优势: 放在文件系统里,任何有服务器登录权限的人都能 ls 看到文件。放在数据库里,文件受到数据库 ACL(访问控制列表)的保护。你可以轻松对 BLOB 字段进行加密存储,随数据库权限管理。
场景三:游戏存档与配置 (Game Saves)
- 特征: 结构复杂的二进制数据,需要原子更新。
- 优势: 很多单机或手游服务端使用 SQLite/MySQL 存储玩家存档。如果更新存档时发生断电,数据库的 WAL (Write-Ahead Log) 机制能保证存档不损坏。
场景四:动态生成的报表/发票
- 特征: 系统生成的 HTML 或 XML 快照。
- 优势: 这些通常是“只读”且“永久归档”的。存入 BLOB 可以方便地随业务数据一起冷备。
4. 什么时候 绝对不要 用 BLOB?
虽然 BLOB 很香,但别走极端。以下情况请老老实实存文件系统或 OSS:
5. 最佳实践总结
如果你决定尝试 BLOB 方案,请遵循以下原则:
- 差评: users (id, name, avatar_blob) -> 查 name 时会拖慢速度。
- 好评: users (id, name) + user_avatars (user_id, avatar_blob)。
- SQLite: 王者。专门为此优化。
- PostgreSQL: TOAST 机制处理大字段非常优秀。
- MySQL: 性能稍弱,注意 max_allowed_packet 配置。







