PostgreSQL 万能论:为什么一家公司可以用它替代 Kafka、Redis、Elastic 与 ClickHouse


难度 中等
编写人 编写内容 编写时间
growdu 翻译整理,原文作者 Dr. Raphael A. Bauer 2026-08-21

本文为 Dr. Raphael A. Bauer 所写 PostgreSQL for Everything 一文的中文翻译整理

  • 原文链接:https://www.raphaelbauer.com/posts/postgresql-everything/
  • 原文发布时间:2024-02-14
  • 译者:本文用我自己的中文技术行文重写了原文观点,并在部分章节补充了 PostgreSQL 源码定位,便于读者自行深入查阅
  • 如有错译,请以原文为准

引子

“宇宙的终极答案不是 42,而是 PostgreSQL。”

这是一句玩笑话,但里面藏着一个真实的故事:在今天的技术栈里,PostgreSQL 已经强大到可以同时扮演多种基础组件的角色——全文检索、文档数据库、消息队列、时序库、向量库、缓存、文件存储、图数据库,乃至一些你不该拿数据库干的活(比如俄罗斯方块)。

如果你想让产品跑得快、运营得简单,PostgreSQL 几乎可以替代一整套周边组件。很多成功公司正在这么做。我们今天就来盘一盘,PG 到底能顶替什么、怎么顶替。


一、PostgreSQL 为什么”够格”做这一切?

在讨论”能不能替代 X”之前,先说清楚 PostgreSQL 本身的两大特质。

1.1 坚如磐石

PG 的稳定性在数据库圈里近乎”另类”:

  • 30+ 年活跃开发的代码库,C 为主
  • MVCC 不阻塞读不阻塞写,并发模型本身就让简单负载非常稳
  • 主版本之间的兼容性强(从 PG 9 升到 PG 18 的 API 变化极小)
  • 配套生态成熟:pgBackRest、pg_stat_statements、pgaudit、pg_hint_plan……

稳定性 = 维护成本低。这是 PG 替代一切的第一前提。

1.2 装、跑、扩——样样简单

# Debian/Ubuntu
sudo apt install postgresql
sudo systemctl start postgresql
# 容器化
docker run --name pg -e POSTGRES_PASSWORD=xxx -d postgres:18
# 云上一键
# AWS RDS、阿里云 PolarDB-PG、腾讯云 TDSQL-PG……

扩缩容也是老套路:

  • 垂直扩:改 shared_buffers、加 CPU、加大盘
  • 水平扩:逻辑复制 + 读写分离;或者用 Citus 这样的扩展做分片

译者注:PG 17 引入了逻辑复制槽 failover增量备份等特性,让 HA 链路进一步简化;源码见 src/backend/replication/logical/worker.c


二、简化你的整套 IT 架构

每一套外部组件都意味着:

  • 多一套监控
  • 多一套备份
  • 多一套权限管理
  • 多一份跨网络流量
  • 多一份故障点

如果 PostgreSQL 能干,那把它合进 PG 的收益就远大于性能上那点微小的差距

下面逐一拆解 PG 可以顶替谁、怎么顶替。


三、PostgreSQL 替代 Solr / Elastic:全文检索

典型替代场景:站内搜索、日志检索、文档检索。

3.1 原生能力

PG 自带 tsvector / tsquery

-- 一行 SQL 建索引
ALTER TABLE articles
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (
        setweight(to_tsvector('english', coalesce(title,'')), 'A') ||
        setweight(to_tsvector('english', coalesce(body,'')), 'B')
    ) STORED;

CREATE INDEX idx_search ON articles USING GIN (search_vector);

-- 查询
SELECT title, ts_rank(search_vector, query) AS rank
FROM articles, to_tsquery('english', 'postgres & replication') query
WHERE search_vector @@ query
ORDER BY rank DESC
LIMIT 10;

3.2 何时够用,何时不够

  • 小到中等规模(千万级文档)、典型 web 搜索:完全够用
  • 语言支持:英语、中文(用 simple 或 zhparser)、日韩……
  • ⚠️ 超大规模 + 复杂聚合:Elastic 的 inverted index + 分布式更适合
  • ⚠️ 复杂相关性 + 机器学习打分:Elastic / OpenSearch 的生态更丰富

译者注:PG 的 GIN 索引(src/backend/access/gin/)对 tsvector 的支持已经多年迭代成熟,足够替代大多数”塞个全文检索”的项目需求。


四、PostgreSQL 替代 MongoDB:JSON 支持

典型替代场景:半结构化数据、配置存储、事件流水。

4.1 两种类型:jsonjsonb

CREATE TABLE events (
    id        bigserial PRIMARY KEY,
    created_at timestamptz DEFAULT now(),
    payload   jsonb NOT NULL
);

-- 索引 jsonb 字段
CREATE INDEX idx_payload_user ON events USING GIN ((payload -> 'user_id'));

-- 查询:找出 user_id = 'u123' 的事件
SELECT * FROM events
WHERE payload @> '{"user_id": "u123"}'
ORDER BY created_at DESC
LIMIT 50;

-- 更新:jsonb 局部修改
UPDATE events
SET payload = payload || '{"processed": true}'
WHERE id = 12345;

jsonb二进制存储 + GIN 索引,性能可与文档库一战。

4.2 何时够用

  • ✅ 半结构化数据 + 偶尔改 schema
  • ✅ 不需要 MongoDB 的水平 sharding 那一套
  • ✅ 团队希望一套 SQL 解决所有查询

⚠️ 强 schema 验证:从 PG 12 起 JSON_SCHEMA 验证可用(PG 15 改名为 pg_jsonschema 扩展)。


五、PostgreSQL 替代 Kafka / RabbitMQ:作为队列

典型替代场景:任务队列、事件驱动、定时任务。

5.1 PG 16+ 原生消息队列

从 PG 16 起,**pg_queue 内置**(早期版本由 pgmq 扩展提供):

-- 创建队列
SELECT pgmq.create('orders');

-- 入队
SELECT pgmq.send('orders', jsonb_build_object('order_id', 12345, 'amount', 99));

-- 出队(带 visibility timeout)
SELECT * FROM pgmq.read('orders', visibility_timeout := 30, qty := 10);

-- 处理完确认
SELECT pgmq.delete('orders', msg_id := 1);

5.2 用 SKIP LOCKED 自己做队列

SKIP LOCKED 是 PG 9.5 引入的杀手锏,让”任务表当队列”非常自然:

-- worker 抢一条未处理的任务
BEGIN;

WITH next_task AS (
    SELECT id, payload
    FROM tasks
    WHERE status = 'pending'
    ORDER BY created_at
    LIMIT 1
    FOR UPDATE SKIP LOCKED
)
UPDATE tasks t
SET status = 'processing', started_at = now()
FROM next_task n
WHERE t.id = n.id
RETURNING t.id, t.payload;

-- ... 处理任务 ...

COMMIT;  -- 自动释放锁

多 worker 并行抢任务,没有 Kafka 也能飞起来

5.3 何时该用真消息队列

  • ✅ 事件流规模上 GB/s
  • ✅ 需要重放历史、回溯消费
  • ✅ 跨语言、跨团队的解耦

译者注:PG 17 还引入了逻辑复制订阅的流式事务streaming = parallel),可以把大事务边生成边 apply,延迟大幅降低。源码见 src/backend/replication/logical/worker.c


六、PostgreSQL 替代 ClickHouse:高吞吐时序数据

典型替代场景:监控指标、IoT 数据、日志聚合。

6.1 TimescaleDB 扩展

CREATE EXTENSION timescaledb;

CREATE TABLE metrics (
    time    timestamptz NOT NULL,
    host    text NOT NULL,
    metric  text NOT NULL,
    value   double precision
);

SELECT create_hypertable('metrics', 'time');

-- 自动 chunk + 压缩
ALTER TABLE metrics SET (
    timescaledb.compress,
    timescaledb.compress_segmentby = 'host, metric'
);

SELECT add_compression_policy('metrics', INTERVAL '7 days');
SELECT add_retention_policy('metrics', INTERVAL '90 days');

6.2 何时够用

  • ✅ 中小规模时序(每天亿级以下)
  • ✅ SQL 兼容性重要(不想为 ClickHouse 学新方言)
  • ✅ 想直接用 JOIN 把时序数据和业务表关联

ClickHouse 在列存压缩 + 极致聚合上仍是王者,但时序场景 TimescaleDB 已经够用 90%。


七、PostgreSQL 作为向量数据库:AI 工作流

典型场景:RAG、相似度搜索、推荐系统。

7.1 pgvector 扩展

CREATE EXTENSION vector;

CREATE TABLE docs (
    id        bigserial PRIMARY KEY,
    content   text,
    embedding vector(1536)  -- OpenAI text-embedding-3 维度
);

CREATE INDEX idx_embedding ON docs USING hnsw (embedding vector_cosine_ops);

-- 相似度搜索
SELECT id, content
FROM docs
ORDER BY embedding <=> $1::vector
LIMIT 10;

支持的距离:vector_cosine_ops / vector_l2_ops / vector_ip_ops,HNSW / IVFFlat 索引都能用。

7.2 实时 LLM 应用

把向量和元数据放一起:

SELECT d.id, d.content, d.metadata
FROM docs d
WHERE d.metadata->>'tenant' = current_setting('app.tenant')
ORDER BY d.embedding <=> $1::vector
LIMIT 10;

不需要单独维护一套向量库,事务一致性、权限、备份都和白名单用户表一起搞定。


八、PostgreSQL 替代 Redis:非持久化高性能缓存

典型替代场景:会话存储、热点数据缓存。

8.1 UNLOGGED 表

CREATE UNLOGGED TABLE session_cache (
    key       text PRIMARY KEY,
    value     jsonb NOT NULL,
    expires_at timestamptz NOT NULL
);

-- 自动过期触发器
CREATE OR REPLACE FUNCTION session_cache_expire() RETURNS trigger AS $$
BEGIN
    DELETE FROM session_cache WHERE expires_at < now();
    RETURN NULL;
END $$ LANGUAGE plpgsql;

CREATE EXTENSION pg_cron;  -- 配合定时清理
SELECT cron.schedule('expire-cache', '*/1 * * * *',
    $$DELETE FROM session_cache WHERE expires_at < now()$$);

UNLOGGED 表:

  • 写不写 WAL(极快)
  • 崩溃会丢数据(适合缓存)
  • 性能可与 Redis 一战

⚠️ UNLOGGED 不能被流复制或逻辑复制,所以在读写分离架构里需要单独处理。

8.2 pgmemcache / 嵌入式方案

对极致延迟敏感,可以配合:

  • Redis 仍然单独用:当 PG 的 cache 失效时回源
  • pg_redis_fdw:把 Redis 当成外部表

九、PostgreSQL 替代文件系统:原始二进制数据

典型场景:图片、音视频、文件片段、IoT 数据。

9.1 blob + Flatbuffers

CREATE TABLE blobs (
    id      bigserial PRIMARY KEY,
    data    bytea NOT NULL
);

-- 存
INSERT INTO blobs (data) VALUES (decode('hex...', 'hex'));

-- 取
SELECT data FROM blobs WHERE id = 12345;

经验之谈:原文作者提到,在他的项目里,PG 读 binary blob 比直接读本地文件系统还快——因为 PG 的 buffer pool + 预读 + 大页缓存已经把这事做得很好。

9.2 配合 Flatbuffers / Protocol Buffers

// 客户端:序列化 → bytea 存入 PG → 反序列化
flatcc_builder_t builder;
flatcc_builder_init(&builder);
flatcc_builder_create_vector(&builder, data, len);
size_t size;
void *buf = flatcc_builder_finalize_buffer(&builder, &size);

PGresult *res = PQexecParams(conn,
    "INSERT INTO blobs (data) VALUES ($1)",
    1, NULL, &buf, &size, NULL, 0);

译者注:在 Linux 上 bytea 的最大大小受 pg_largeobject(TOAST)机制支持,理论上最大 1GB / 字段。


十、PostgreSQL 替代图数据库:层级数据

典型场景:组织架构、标签树、评论嵌套。

10.1 LTREE 扩展

CREATE EXTENSION ltree;

CREATE TABLE categories (
    id        serial PRIMARY KEY,
    name      text NOT NULL,
    path      ltree  -- 例如 '1.5.12' 代表 1 → 5 → 12 的路径
);

INSERT INTO categories (name, path) VALUES
    ('Electronics', '1'),
    ('Computers',   '1.1'),
    ('Laptops',     '1.1.1'),
    ('Phones',      '1.2'),
    ('Smartphones', '1.2.1');

-- 查所有"Electronics"的后代
SELECT * FROM categories WHERE path <@ '1';

-- 查所有祖先
SELECT * FROM categories WHERE path @> '1.1.1';

-- 找兄弟节点
SELECT * FROM categories WHERE path ~ '1.1.*';

比 SQL 递归 CTE 简洁一万倍,性能也好很多。


十一、PostgreSQL 替代微服务:JSON 输出

典型观察:很多”微服务”本质上就是”取数据 → 转 JSON → 返回”。PostgreSQL 天生就能干这事

SELECT json_build_object(
    'id', u.id,
    'name', u.name,
    'orders', (
        SELECT json_agg(row_to_json(o))
        FROM orders o
        WHERE o.user_id = u.id
    )
) AS user_json
FROM users u
WHERE u.id = $1;

一行 SQL 输出完整嵌套 JSON,无需中间层。

11.1 利与弊

维度 用 PG 直接出 JSON 用中间层
性能 ✅ 跳过网络 + 序列化开销 ⚠️ 多一跳
灵活性 ⚠️ 复杂业务逻辑难表达 ✅ 任意逻辑
缓存 ⚠️ PG 没专用 HTTP 缓存 ✅ Redis/Cloudflare
鉴权 ✅ PG RLS 一致性 ✅ 各管各的

结论:简单 CRUD + 列表/详情页 → PG 直接出 JSON 完胜;复杂业务流 → 中间层仍不可替代。

推荐阅读:Lukas Eder 的 “Stop Mapping Stuff in Your Middleware”(SQL/XML/JSON 优先,原文不特指 PG 但 PG 完全适用)


十二、彩蛋:PostgreSQL 替代你的 PlayStation 5

有人用 PG 的公用表表达式(CTE) 写了俄罗斯方块:

-- 摘自 https://github.com/nuno-faria/tetris-sql/blob/main/game.sql
WITH ... AS (...)
SELECT ... FROM ...
WHERE ...

不推荐家用,但证明 PG 的图灵完备性 + 表达力。


十三、结论:少即是多

上面列的并不完整。PG 是个极其灵活的软件,并且可以通过插件(extension)不断扩展新能力。

You need simplicity if you want to move fast.

每当你遇到一个新需求,先问自己:

“PG 能干吗?我们真的需要那门新技术吗?”

PostgreSQL 可能不是一切的答案——但它能顶的事比你想象的要多得多


译者补充:源码级视角的 PG 扩展能力

下面这张表把上面提到的能力对应到 PG 源码位置,方便你按图索骥:

能力 扩展 / 模块 源码路径
全文检索 内置 src/backend/utils/adt/tsvector.ctsquery.c
GIN 索引 内置 src/backend/access/gin/
JSON / JSONB 内置 src/backend/utils/adt/jsonb.c
消息队列 (pgmq) 扩展 https://github.com/tembo-io/pgmq
SKIP LOCKED 内置 src/backend/executor/nodeLockRows.c
时序 (timescaledb) 扩展 https://github.com/timescale/timescaledb
向量 (pgvector) 扩展 https://github.com/pgvector/pgvector
HNSW 索引 扩展 https://github.com/pgvector/pgvector
LTREE 内置 src/backend/utils/adt/ltree*.c
UNLOGGED 表 内置 src/backend/access/heap/heapam.c
字节流 (bytea) 内置 src/backend/utils/adt/varlena.c
JSON 输出 内置 src/backend/utils/adt/json.c

参考资料


文章作者: growdu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 growdu !
  目录
分类导航
随笔2 AI27 算法1 计算机基础13 博客搭建7 ChatGPT2 集群63 计算机通信1 数据库34 数据库深入80 DPDK26 Docker11 Elasticsearch4 编辑工具4 FAQ1 Go Web1 hometown2 编程语言16 网络9 OPC1 Linux38 openGauss4 页面12 PostgreSQL54 程序员自我修养1 协议11 成长之路1 stock1 存储5 工具20 VPP18 视频作品1 Vue13 Web1 代码示例11 数据库15 BenchmarkSQL1 PostgreSQL 源码修炼之路14
最热文章
1
13 逻辑复制深入
数据库深入🔥 1570
2
0 Postgresql存储、索引及系统优化、主备切换
PostgreSQL🔥 1495
3
一文读懂openguass dcf网络模块
集群🔥 1420
4
逻辑复制源码分析
数据库深入🔥 1327
5
PostgreSQL 分区表:从一行 `PARTITION BY` 到路由热路径的全链路拆解
数据库🔥 1094
6
applyparallelworker.c 之 LA 端源码深度解析:Leader Apply Worker 的指挥中枢
数据库深入🔥 1082
7
PostgreSQL Background Worker 全解:从 `RegisterBackgroundWorker` 到逻辑复制 4 类 worker 的全生命周期
数据库🔥 1078
8
PostgreSQL的后台进程walsender分析 - 关系型数据库 - 亿速云
PostgreSQL🔥 1033
9
PostgreSQL 逻辑复制的监控:六张视图 + 一组可执行 SQL,把 publisher/subscriber 的速率与健康度彻底看透
数据库🔥 1032
10
PostgreSQL 逻辑复制支持 DDL 之后:DDL 与 DML 的时序难题(重点:分区表)
数据库🔥 999
11
reorderbuffer.c 源码深度解析:PostgreSQL 逻辑复制的"事务重组引擎
数据库深入🔥 953
12
PostgreSQL 内核开发:读取一张表的 9 步标准流程与缓存全景
数据库🔥 938
13
从 `postgres` 二进制到生产级守护 —— PostgreSQL 最外层模块与启动全流程拆解
数据库🔥 936
14
支持逻辑复制同步 DDL 适配 SQL Server 方案
数据库深入🔥 934
15
PostgreSQL 逻辑复制的 ReorderBuffer 与事务机制:从一行 WAL 到一致性变更流的全链路绑定
数据库🔥 913
16
DDL同步架构(美化版)
数据库深入🔥 908
17
PostgreSQL Latch 机制详解:从一行 SetLatch 到 epoll 的内核之旅
数据库🔥 871
18
pgbench 源码全解:一个 C 文件如何撑起 PostgreSQL 官方压测工具
数据库🔥 860
19
PostgreSQL libpq 机制与缓冲区详解
数据库🔥 850
20
PostgreSQL 逻辑复制 spill 文件深度剖析:从 `xid-*.spill` 到 TPC-C 的增长方程
数据库🔥 845