#11 PostgreSQL 与 MySQL 的 JSON 类型:Go 项目怎么选
MySQL PostgreSQL JSON 2026-09-14关系型数据库支持 JSON 已经很成熟,但 JSON 并不意味着可以随意替代普通字段。实际项目中,更重要的问题是:PostgreSQL 的 json 和 jsonb 怎么选?MySQL JSON 如何建立索引?Go 又应该怎样读写?
coding in a complicated world
关系型数据库支持 JSON 已经很成熟,但 JSON 并不意味着可以随意替代普通字段。实际项目中,更重要的问题是:PostgreSQL 的 json 和 jsonb 怎么选?MySQL JSON 如何建立索引?Go 又应该怎样读写?
同样叫 Timestamp,MySQL 和 PostgreSQL 的语义并不相同,也是跨库迁移和应用开发中最容易踩坑的地方。
这篇文章(Dr. Raphael A. Bauer 的《PostgreSQL for Everything》)的核心论点是:PostgreSQL 不是万能答案,但能覆盖你想象中多得多的场景;在中小规模下,先用 PG 统一数据层,遇到真实瓶颈再换专用系统,是更省维护成本、更快交付的架构选择。
PostgreSQL 凭借“老牌稳定 + 现代特性 + 插件生态”,在初创和中型业务里可以一个数据库顶住搜索、文档、队列、时序、向量、缓存、层级数据等多套中间件;它的真正价值不是性能碾压专用库,而是用更低的运维与认知成本,让你把时间花在业务功能上。
作者用自己 CTO 生涯的实战说明,以下场景不必急着引入专用组件:
| 原本的专用系统 | PostgreSQL 方案 | 关键机制 |
|---|---|---|
| MySQL + Lucene/Solr | 原生全文检索 | tsvector + GIN 索引(Contentful、Instacart 实践) |
| MongoDB | 文档存储 | jsonb + GIN,支持 JSONPath 查询 |
| Kafka / RabbitMQ / SQS | 表即队列 | FOR UPDATE SKIP LOCKED、递归/游标消费,先 PG 后换 MQ |
| ClickHouse / InfluxDB | 时序数据 | TimescaleDB 超表 + 连续聚合 |
| Pinecone / 专用向量库 | 向量检索 | pgvector,pgai 做 embedding 同步与 RAG |
| Redis 缓存 | 内存级缓存 | UNLOGGED 表 + 触发器模拟 TTL,多数用例够快 |
| 文件系统存小二进制 | Blob 列 | Flatbuffers 序列化入 bytea,缓存策略下比裸文件 IO 更快 |
| 树形/层级数据 | LTREE 类型 | 比递归 CTE 更易维护 |
| 微服务中间层 | 直接出 JSON | 查询里拼 JSON 返回,省一层应用中间层 |
作者强调:这些都是“先 PG 起步”的策略,不是否认专用系统——当吞吐/并发/规模真正打满时,再切 Kafka、ClickHouse、Redis 不迟。
这篇文章带来很好的启发:PostgreSQL拥有多模型存储能力,原生支持文档(jsonb)、轻量缓存、全文检索、向量检索、队列表等场景。在不少业务场景下,可以优先基于PG实现相关能力,避免盲目引入新的中间件,降低系统复杂度。
但我不认同将其作为一套可直接落地的生产级通用方案,存在明显边界约束(架构收敛不能牺牲稳定性):
适用场景:
Supabase 是一个以 PostgreSQL 为核心的开源 Backend-as-a-Service(BaaS)平台,定位类似 Firebase,但采用 PostgreSQL 作为核心数据库。它通过多个独立服务提供完整的 Backend 能力。
PostgREST 2014 年前后提出并验证了“PostgreSQL 直接作为 Backend、自动生成 REST API”这条路线。
2016 年,pREST 作者认为 Haskell 在他们的团队环境中招聘和维护成本较高,因此选择 Go 来重新实现。
二者定位高度重合,核心共同点都是把 PostgreSQL 数据库直接转换成 REST API,减少传统 Backend 中 Controller、CRUD Repository 等代码。
没有深入使用,暂时不了解两者在技术栈、扩展能力和设计理念的细致差别。
pREST
官网:https://www.prestd.com/
文档:https://docs.prestd.com/
GitHub:https://github.com/prest/prest
PostgREST
官网:https://postgrest.org
GitHub:https://github.com/PostgREST/postgrest
Supabase
值得介绍的是,PostgREST 是开源的 Backend-as-a-Service 平台 Supabase 的核心组件之一。
PS:Supabase 主要开发语言是 TypeScript。
https://github.com/supabase/supabase
Supabase 在 PostgREST 这类 PostgreSQL API 层之上进一步提供了认证、实时通信、对象存储、Serverless Functions 等完整 Backend 能力,还自带完整的 Web 管理控制台(Supabase Studio),可以让开发者基于 PostgreSQL 快速搭建 Web 和移动应用。
项目 Slogan 就是:Build in a weekend. Scale to millions.
PS:Supabase 自带的 Web 管理控制台主要用于管理数据库、认证、Storage、API 等基础设施,并不是面向最终业务人员的业务后台,业务系统的管理后台仍然需要自己开发。
GIN(Generalized Inverted Index)是 PostgreSQL 的倒排索引,适合一个字段包含多个可搜索元素的场景,典型应用包括 jsonb、数组和全文检索。
PostgreSQL 对 JSON 的支持不仅限于存储数据。实际开发中,jsonb 更常用,因为它会以二进制格式存储 JSON,并提供结构化查询、修改和索引能力。对于字段结构存在一定变化、但又希望直接利用数据库查询能力的业务数据,jsonb 是比较合适的方案。

面向进程模型是一种数据库系统的架构模型,核心思想是将不同的数据库服务分配给不同的进程,每个进程独立运行,相互之间通过进程间通信(IPC)进行协作。
这种模型被广泛应用于数据库系统中,例如 PostgreSQL 数据库系统。
正如上文所说,进程模型使得 PostgreSQL 可以将不同的服务分配给多个进程独立运行,每个进程负责不同的任务,例如查询处理、并发控制、锁管理等。
进程模型还可以可以保证系统的稳定性和可靠性。当一个进程出现问题时,不会影响到其他进程的正常运行,从而提高了系统的可用性。
这样的特点使得 PostgreSQL 可以同时处理大量的并发请求,提高了系统的性能和响应速度;
除此之外,PostgreSQL 还可以很容易地进行水平扩展,增加更多的节点以应对更高的负载。
不过与此同时,也让 PostgreSQL 面对着管理和维护成本相对较高、需要较为复杂的进程间通信和协调机制、需要消耗更多的系统资源等缺点。
6 月初,Heikki Linnakangas 发布了将 PostgreSQL 转为线程模型的提案。

线程模型是一种数据库系统的架构模型,与面向进程模型类似,它是将不同的数据库服务分配给不同的线程,每个线程独立运行,相互之间通过线程间通信进行协作。线程模型在一些轻量级的数据库系统中得到广泛应用,例如 SQLite。
线程模型与进程模型的最大区别在于,线程模型中所有的线程共享同一个进程的地址空间,每个线程有自己的堆栈,共享代码段和数据段。这意味着线程之间可以直接访问同一份内存,因此线程间通信的成本相对较低,不过这也意味着线程间的数据共享可能会带来安全性问题。
从进程模型转换成线程模型的优缺点:
优点
缺点
PostgreSQL 开发者、EnterpriseDB 高级数据库架构师 Andres Freund 指出:
我认为原有流程模型开始产生诸多限制,这个问题在大型设备上体现得尤其明显。
跨进程上下文切换所带来的开销,原本就比在同一进程内的不同线程间切换要更高 —— 我估计这种开销还将持续提升。
面对大量连接,整个体系最终一定会因 TLB 未命中而浪费大量时间。
这是进程模型无法跨进程共享 TLB 的天然属性造成的必然结果。

目前这还仅仅只是一项提议,并且由于 PostgreSQL 被广泛用于生产环境,转换到线程模型的过程需要非常谨慎。开发团队需要在不影响现有生产环境的情况下测试新的线程模型,以确保其稳定性和可靠性。即便这个提议通过,这个转化过程肯定也是无法通过单一版本彻底完成,从网上的各方评价来看,目前大多数人都支持这项提议。