为什么 MongoDB 使用 BSON?而不是JSON
MongoDB 选择使用 BSON (Binary JSON) 而不是直接使用纯文本的 JSON,主要是为了解决 JSON 在性能、空间效率和数据类型支持上的局限性。
虽然 JSON 对人类阅读非常友好,但对于数据库这种需要高频读写、索引和计算的系统来说,它并不是最高效的格式。
以下是 MongoDB 使用 BSON 的三个核心原因:
1. 更快的遍历和解析速度 (性能)
这是最主要的原因。
- JSON (文本扫描): JSON 是纯文本格式。如果要在一个大的 JSON 文档中查找某个字段(例如查找
{ "a": ..., "z": 1 }中的z),计算机必须逐个字符扫描整个字符串,匹配括号和引号,才能找到字段的结束位置和下一个字段的开始位置。这非常消耗 CPU。 - BSON (长度前缀): BSON 是二进制格式。它在存储对象或数组时,会在头部记录该元素的字节长度。
- 优势: 如果数据库只需要读取文档中的某个特定字段,或者需要跳过某个嵌套的子文档,它可以直接读取长度信息,然后直接“跳”过相应的字节数,而不需要扫描其中的内容。这使得 MongoDB 在进行查找、索引和更新操作时速度极快。
2. 更丰富的数据类型 (类型保真度)
JSON 的数据类型非常有限,无法满足现代应用程序和数据库的复杂需求。
JSON 的局限: JSON 只有
String,Number,Boolean,Array,Object,Null。- 日期问题: JSON 没有“日期”类型,通常只能存为字符串(如 "2023-10-27T10:00:00Z")。数据库在进行日期范围查询或排序时,必须先将字符串解析为时间戳,效率很低。
- 数字精度: JSON 的
Number通常被视为双精度浮点数。它无法区分Int32(整型)、Int64(长整型)和Decimal(高精度小数)。这在金融计算中是致命的。 - 二进制数据: JSON 无法直接存储图片或文件。必须将其转为 Base64 字符串,这会使数据体积增加约 33%,且编解码消耗 CPU。
BSON 的扩展: BSON 扩展了类型系统,原生支持:
- Date: 直接存储为 64 位整数(毫秒时间戳),排序和计算极快。
- BinData: 原生二进制数据(可以直接存图片缩略图或加密数据)。
- ObjectId: MongoDB 默认的主键类型,生成速度快且全局唯一。
- 数值类型: 明确区分
Int32,Int64,Double,Decimal128。
3. 编解码效率与空间 (权衡)
- 编码/解码: 计算机处理二进制数据(BSON)比解析文本(JSON)要快得多。将内存中的对象转换为 BSON(序列化)或从 BSON 转回对象(反序列化)的开销更小,这对高并发数据库至关重要。
- 空间占用 (由情况而定):
- JSON: 存储数字比较浪费空间(例如数字
1234567890在 JSON 中占 10 个字节的字符)。 - BSON: 存储数字很省空间(
Int32永远只占 4 字节)。 - 注意: BSON 并不总是比 JSON 小。因为 BSON 需要存储字段长度和类型标识符,对于全是小字符串的简单文档,BSON 可能比 JSON 略大一点。但 MongoDB 认为用少量的空间换取巨大的时间(速度)优势是值得的。
- JSON: 存储数字比较浪费空间(例如数字
总结对比
| 特性 | JSON | BSON |
|---|---|---|
| 全称 | JavaScript Object Notation | Binary JSON |
| 格式 | 纯文本 (UTF-8) | 二进制 |
| 解析方式 | 必须逐字符扫描 (慢) | 可利用长度头进行跳跃 (快) |
| 数据类型 | 少 (无日期、无二进制) | 多 (支持 Date, BinData, Int64 等) |
| 主要用途 | 数据交换 (API, Config) | 数据存储 (数据库内部格式) |
| 人类可读性 | 高 | 不可读 (乱码) |
一句话总结:
MongoDB 使用 BSON 是为了在保持 JSON 灵活性的同时,获得像传统关系型数据库一样的性能和丰富的数据类型支持。