JSONB vs. BSON:追踪 PostgreSQL 与 MongoDB 的 Wire 协议
Source: Dev.to
概览
MongoDB 的 BSON 与 PostgreSQL 的 JSONB 之间存在本质区别。两者都是二进制 JSON 格式,但它们的角色不同。JSONB 纯粹是 PostgreSQL 中 JSON 数据的内部存储格式。BSON 则是 MongoDB 的原生数据格式:它被应用程序驱动用于与数据库通信,同时也作为磁盘上的存储格式。
关键区别
- 目的
- JSONB – 为 PostgreSQL 内部的存储和查询进行优化。
- BSON – 为在 MongoDB 中的网络传输和磁盘存储而设计。
- 数据类型
- JSONB 支持 JSON 类型的子集(对象、数组、字符串、数字、布尔值、null)。
- BSON 额外添加了诸如
ObjectId、Date、Binary、Decimal128等类型。
- 大小开销
- BSON 为类型信息和长度前缀保留了额外字节,使得相同数据下它的体积略大于 JSONB。
- 索引
- PostgreSQL 可以使用 GIN/GiST 索引对 JSONB 字段建立索引。
- MongoDB 直接在 BSON 字段上提供索引。
跟踪 PostgreSQL Wire Protocol
PostgreSQL 使用自己的 wire protocol 与客户端通信。要检查原始消息:
# Using pg_recvlogical to capture logical replication messages
pg_recvlogical \
--dbname=postgres \
--slot=debug_slot \
--start \
--verbose
或使用 tcpdump:
sudo tcpdump -i any -w pg.pcap port 5432
随后可以在 Wireshark 中打开捕获文件,并使用过滤器 postgresql 来解码协议消息。
跟踪 MongoDB Wire Protocol
MongoDB 使用 BSON wire protocol。捕获流量的一个简便方法是结合 mongodump 与 tcpdump:
# Capture traffic on default MongoDB port 27017
sudo tcpdump -i any -w mongo.pcap port 27017
在 Wireshark 中使用过滤器 mongodb 解码消息。你会看到诸如 OP_QUERY、OP_INSERT 以及它们的 BSON 负载等操作。
示例:解码 BSON 文档
假设你捕获到了以下原始字节(十六进制):
16 00 00 00 02 66 6f 6f 00 04 00 00 00 62 61 72 00 00
解释:
| 偏移 | 字节 | 含义 |
|---|---|---|
| 0‑3 | 16 00 00 00 | 文档长度(22 字节) |
| 4 | 02 | 类型:字符串 |
| 5‑7 | 66 6f 6f | 键:foo |
| 8 | 00 | 键的空字符终止符 |
| 9‑12 | 04 00 00 00 | 字符串长度(4) |
| 13‑15 | 62 61 72 | 值:bar |
| 16 | 00 | 值的空字符终止符 |
| 17‑21 | 00 00 00 00 | 文档结束标记 |
何时使用哪种格式
- 使用 JSONB 当你在 PostgreSQL 中工作,需要强大的 SQL 查询能力、索引以及事务保证时。
- 使用 BSON 当你与 MongoDB 交互,尤其是需要 MongoDB 特有的数据类型或想利用其灵活的模式和分片特性时。
理解 wire protocol 与底层二进制格式,有助于在调试性能问题、构建自定义驱动或仅仅是深入了解这些数据库在底层是如何运作时提供帮助。