JSON 和 JSONB 最大的区别之一就是数据存储的格式。JSON 是以文本形式保存数据,而 JSONB 是以二进制形式存储。也就是说:
- JSON 会把你传进来的数据原样保存。比如你插入
{"title": "PostgreSQL", "tags": ["database", "SQL"]}这串,它就会按原样存下来。 - JSONB 会先解析 JSON 对象,去掉多余的空格,把 key 排序,优化结构,然后再以二进制格式存储。
这种优化让 JSONB 在处理数据时更快,特别是做复杂的过滤、查找和排序操作时。
读写性能对比
JSON 和 JSONB 在读写速度上各有特点:
- JSON 写入数据库更快,因为不用在保存前解析数据。但读取和处理时会慢点,因为 PostgreSQL 查询时还得重新解析数据。
- JSONB 写入时会慢点,因为保存前要处理数据。但读取、过滤和取值都快很多,所以做分析或搜索类的需求更推荐用 JSONB。
举个例子:
-- 创建带 JSON 和 JSONB 的表
CREATE TABLE json_example (data JSON);
CREATE TABLE jsonb_example (data JSONB);
-- 插入数据
INSERT INTO json_example VALUES ('{"key": "值", "tags": ["json", "例子"]}');
INSERT INTO jsonb_example VALUES ('{"key": "值", "tags": ["jsonb", "例子"]}');
-- 过滤数据
SELECT * FROM json_example WHERE data->'key' = '"值"'; -- 慢
SELECT * FROM jsonb_example WHERE data->'key' = '"值"'; -- 快
数据索引
JSONB 最大的优势之一就是支持索引。PostgreSQL 可以给 JSONB 列建索引,用 GIN 类型的索引,大大加快查找和过滤速度。
建索引的例子:
-- 给 JSONB 列建索引
CREATE INDEX idx_jsonb_tags ON jsonb_example USING gin (data->'tags');
而 JSON 不支持索引,所以做复杂查找和过滤时就没那么合适了。
什么时候用 JSON,什么时候用 JSONB
JSON 比较适合这些场景:
- 你想原样保存数据,不做任何改动。
- 你不打算经常用 JSON 数据做过滤、查找或排序。
- JSON 数据主要是要原样传给别的系统或者客户端(比如 API 给前端返回)。
例子:
-- 不分析直接存 JSON
CREATE TABLE api_responses (
id SERIAL PRIMARY KEY,
response JSON
);
-- 插入 API 传来的数据
INSERT INTO api_responses (response)
VALUES ('{"status": "成功", "payload": {"id": 123, "name": "John"}}');
JSONB 适合这些情况:
- 你打算经常根据 JSON 里的值做过滤、查找、分组或排序。
- 你更看重数据读取的性能,而不是写入速度。
- 你想用索引来加速 JSON 数据的操作。
例子:
-- 用 JSONB 存分析和嵌套对象
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSONB
);
-- 插入数据
INSERT INTO products (details)
VALUES ('{"name": "笔记本", "price": 1200, "tags": ["电子产品", "电脑"]}');
-- 查找带 "电子产品" 标签的商品
SELECT * FROM products
WHERE details @> '{"tags": ["电子产品"]}';
关于 @> 和 --> 操作符的更多用法,咱们下节课再聊 :P
JSON 和 JSONB 的操作例子
我们来建两个表:一个用 JSON 列,一个用 JSONB:
CREATE TABLE json_table (
id SERIAL PRIMARY KEY,
data JSON
);
CREATE TABLE jsonb_table (
id SERIAL PRIMARY KEY,
data JSONB
);
插入数据,两张表的写法都一样:
INSERT INTO json_table (data)
VALUES ('{"key": "值", "tags": ["json", "例子"]}');
INSERT INTO jsonb_table (data)
VALUES ('{"key": "值", "tags": ["jsonb", "例子"]}');
现在我们来查 key 为 值 的数据:
-- 对 JSON
SELECT * FROM json_table
WHERE data->>'key' = '值';
-- 对 JSONB
SELECT * FROM jsonb_table
WHERE data->>'key' = '值';
数据量小的时候,性能差别几乎看不出来。但如果有几百万行,JSONB 的表现会好很多,尤其是你建了索引的话:
CREATE INDEX idx_jsonb_key ON jsonb_table USING gin ((data->>'key'));
处理嵌套对象和数组,JSONB 也更高效:
-- 从数组里取值
SELECT data->'tags'->>0 AS first_tag
FROM jsonb_table;
优缺点总结
| 特点 | JSON | JSONB |
|---|---|---|
| 数据存储 | 原样以文本格式保存数据 | 以二进制格式保存,key 会排序 |
| 写入性能 | 更快,因为直接存原始数据 | 慢点,因为要先解析 |
| 读取性能 | 慢点,因为查询时要解析数据 | 更快,因为数据已经优化好 |
| 索引 | 不支持 | 支持(GIN、BTREE 索引) |
| 过滤 | 慢 | 快 |
| 操作支持 | 有限 | 更丰富 |
到底选 JSON 还是 JSONB,得看你的需求。如果只是想原样存文本数据,直接用 JSON 就行。如果你要在列里频繁操作、过滤、查找、分组,JSONB 会更高效也更方便。
对于复杂应用,如果 JSON 数据不仅仅是“存着”,还要经常做分析,JSONB 就是神器。所以,实在拿不准就选 JSONB,说不定以后你写的“人生最快 SQL”就靠它了!
GO TO FULL VERSION