PostgreSQL 同时支持 json 和 jsonb。
最实用的结论是:
业务里大多数场景优先用 jsonb。
原因很简单:
json保留原始文本形式jsonb会转成更适合处理的二进制结构jsonb支持索引,查询通常更高效
比如给通行证附上半结构化信息:
UPDATE permits
SET meta = jsonb_build_object(
'channel', 'mobile',
'reviewer', 'robot-3',
'tags', jsonb_build_array('fast-lane', 'night')
)
WHERE permit_id = 42;查 JSONB 内容:
SELECT permit_id, meta
FROM permits
WHERE meta @> '{"channel":"mobile"}';取字段:
SELECT
permit_id,
meta ->> 'reviewer' AS reviewer
FROM permits;给 JSONB 建 GIN 索引:
CREATE INDEX idx_permits_meta_gin
ON permits USING GIN (meta);如果你的查询大多是 containment / jsonpath 匹配,还可以考虑:
CREATE INDEX idx_permits_meta_path_gin
ON permits USING GIN (meta jsonb_path_ops);要点是:
jsonb_ops更通用jsonb_path_ops更小、更快,但支持的操作符更窄
如果你经常只查某个 JSON 路径,表达式索引更划算:
CREATE INDEX idx_permits_meta_tags
ON permits USING GIN ((meta -> 'tags'));但要记住一句非常重要的话:
JSONB 是给“边缘字段、变化字段、外部载荷”用的,不是让你把整个业务模型全塞进一个大 JSON。
下面这种设计通常是坏味道:
permits(
id bigint,
data jsonb -- 把所有字段都塞进去
)因为这样你会失去:
- 清晰约束
- 外键关系
- 精准类型
- 更稳定的优化空间
正确姿势通常是:
稳定主干字段 -> 正规列
变化较大的附加信息 -> JSONB