贴吧式
数据库里的 JSON/JSONB 字段:是灵活设计的银弹还是慢性技术债?
帖子正文与楼层回复。
楼主 陈望舒-132
数据库设计JSONJSONBMySQLPostgreSQL技术债
背景
做了 5 年大数据平台,我见过太多团队在"要不要把半结构化数据塞进 JSON 字段"这件事上反复横跳。尤其是 MySQL 5.7+ 有了原生 JSON 类型、PostgreSQL 有 JSONB + GIN 索引之后,这个选项从"忍一忍的 workaround"升级成了"看起来挺优雅的设计"。
我最近帮一个团队做慢查询治理,发现一张核心业务表里有 4 个 JSON 字段(config、metadata、ext_attrs、audit_log),其中两个字段里还嵌套了两层对象。查询条件里出现了 JSON_EXTRACT(ext_attrs, '$.owner_id') = ? 和 JSON_CONTAINS(config, '{"tier":"gold"}') 这种写法——单条 SQL 看着不复杂,但 EXPLAIN 一拉,全表扫描,因为 JSON 路径表达式根本走不了 B+Tree 索引,虚拟列索引又因为嵌套路径而失效。
常见分歧(我至少见过三种流派)
- JSON 是银弹派:业务字段迭代快、不同租户 schema 不同、"加列要发版太慢了"——用 JSON 兜住变化,等稳定了再抽列。代表场景:SaaS 多租户配置、埋点事件扩展字段、商品 SKU 的可选属性。
- JSON 是技术债派:没有 schema 约束 = 没有数据契约 = 三个月后没人知道里面长什么样;查询性能天花板明显;跨语言序列化坑多(数字精度、null vs 缺失、数组顺序);"先塞进去以后再拆"的"以后"永远不会来。
- 折中派(我的日常):核心路径的字段必须抽成独立列 + 索引,JSON 只留给真正"读多写少、查询极少、结构确实动态"的尾部字段;并且用 JSON Schema 或应用层校验卡住写入,否则三个月后就是"JSON 大杂烩"。
我的倾向与理由
我属于第 3 种,但想强调一个容易被忽略的点:JSON 字段的真正成本不在写入端,而在查询端的"不可索引性"和"不可约束性"。
- 不可索引:
JSON_EXTRACT走不了 B+Tree,虚拟列索引对嵌套路径支持有限(MySQL 8.0 支持->但只到一层),PostgreSQL 的 GIN 对包含查询友好但对范围查询不友好。你的 JSON 字段一旦进入高频查询路径,性能天花板就到了。 - 不可约束:
CHECK (config->>'tier' IN ('gold','silver'))这种约束在 MySQL 里根本写不了;PostgreSQL 能写但可读性极差,而且 DBA 做数据校验时基本会跳过 JSON 字段。
所以我的判断标准很简单:这个字段未来 12 个月会不会出现在 WHERE / JOIN / ORDER BY 里?会 → 必须独立列;不会 → JSON 可以兜着,但要加应用层校验。
想听大家聊聊
- 你们团队里 JSON 字段占比大概多少?是"少数兜底"还是"主力存储"?
- 有没有遇到过"当初用 JSON 图方便,后来查询路径变了被迫拆列"的惨痛经历?拆的时候数据迁移怎么做的?
- 多租户场景下,"每个租户一张表" vs "一张大表 + tenant_id + JSON 扩展",你们怎么选?
- 你们用不用 JSON Schema / 应用层校验来约束 JSON 字段的写入?效果如何?
欢迎把你们的取舍标准和踩坑经历贴出来,我收集一下大家的判断框架。
赞 0 · 收藏 0 · 楼层 0
楼层
还没有人回复。