很多人学习 PostgreSQL 时,都会有一个印象:它是关系型数据库,擅长表、列、约束和 JOIN。
这个印象没有错,但还不完整。
PostgreSQL 还有一个很实用的特点:它既能处理传统关系型数据,也能处理一定程度的半结构化数据。
这就是 JSON 和 JSONB 发挥作用的地方。
现实业务里,并不是所有数据都适合在一开始就完全拆成固定列。
例如:
这些数据的共同特点是:
这时如果强行把所有内容都拆成固定列,表结构可能会很僵硬;而完全放弃关系型表结构,又会失去约束和查询能力。
PostgreSQL 支持 JSON,就是为了在这两者之间提供一种折中。
这两个类型都能存 JSON 格式的数据,但它们的定位并不完全一样。
JSON 更接近“按原始 JSON 文本保存”。
它适合“我需要保存 JSON 这类结构化文本”的场景。
JSONB 则更偏向“为了查询和处理而优化的二进制表示”。
对初学者来说,最重要的直觉是:
JSON:更像保留原始 JSON 文本JSONB:更适合后续查询、筛选、索引所以在 PostgreSQL 的日常业务里,如果你不仅仅是“存进去”,还希望“经常查里面的字段”,通常更常见的是 JSONB。
CREATE TABLE events (id integer PRIMARY KEY,event_name text NOT NULL,properties jsonb,created_at timestamp DEFAULT NOW());
这里的 properties 可以保存半结构化属性,例如:
{"page": "/pricing","browser": "Chrome","country": "CN"}
这让你在保留主干表结构的同时,也能给每条事件带上灵活字段。
你可以把 PostgreSQL 想成:
jsonb例如用户表:
CREATE TABLE users (id integer PRIMARY KEY,name text NOT NULL,email text NOT NULL,profile jsonb);
这里:
id、name、email 是核心强约束字段profile 可以放头像、主题偏好、额外展示信息等扩展属性这种设计在很多业务里都很常见。
SELECT properties -> 'browser'FROM events;
这会返回 JSON 形式的值。
SELECT properties ->> 'browser'FROM events;
这里的 ->> 更适合拿文本结果。
SELECT id, event_nameFROM eventsWHERE properties ->> 'country' = 'CN';
这表示只查 country 为 CN 的事件。
SELECT id, event_nameFROM eventsWHERE properties @> '{"browser": "Chrome"}';
这条语句的直觉是:properties 中至少包含这段键值结构。
当你开始频繁按 jsonb 内容查询时,单纯存数据还不够,性能也会成为问题。
这时常见的做法是给 jsonb 字段建立 GIN 索引。
例如:
CREATE INDEX idx_events_properties_ginON events USING GIN (properties);
初学者可以先记住这个结论:
jsonb 常配合 GIN 索引这也是前面索引章节里提到 GIN 的典型使用场景之一。
例如用户偏好、页面设置、开关项。
例如不同类型商品带有不同附加属性,但你又不想为每一种变化频繁改表结构。
埋点、日志、行为事件常常会带一批动态字段。
例如某些第三方接口返回的结构中,有一部分需要保留原始属性。
这是非常重要的一点。
JSONB 很方便,但不代表核心字段都应该往里放。
例如下面这些字段,通常更适合做成普通列:
原因很简单:
更稳妥的思路通常是:
jsonbCREATE TABLE products (id integer PRIMARY KEY,name text NOT NULL,price numeric(10, 2) NOT NULL,attributes jsonb);
这里:
id、name、price 是稳定的核心字段attributes 可以按商品类别存不同的扩展属性例如图书类商品:
{"author": "Alice","isbn": "978-7-xxx","language": "zh-CN"}
而服饰类商品可能是:
{"color": "black","size": "L","material": "cotton"}
这就是半结构化数据真正有价值的地方。
可以先遵循一个简单原则:
jsonbGIN 索引你现在最重要的是建立这些判断:
JSON 和 JSONB 都能存 JSON,但 JSONB 更适合查询和索引->、->> 和 @>GIN 索引常用来加速 jsonb 查询jsonb下一篇是附录性质的命令速查,会把常见的 psql 连接和查看命令集中整理出来,方便回头查。