Postgres
技术极简主义:一切皆用Postgres
# 前言
在当今这个技术栈爆炸的时代,我们常常陷入"过度工程化"的陷阱:一个Web应用需要Redis缓存、MongoDB文档存储、Elasticsearch搜索、ClickHouse分析... 然后发现运维团队已经集体辞职了。🤷♂️
两年前,当我负责重构公司核心系统时,我决定拥抱一个"偏执"的理念:一切皆用Postgres。这个看似极端的选择,却意外地带来了惊人的工程效率提升。今天想聊聊这个"数据库独裁主义"背后的思考与实践。
提示
"最好的技术是让你感觉不到技术的技术"
——PostgreSQL社区隐士
# 为什么是Postgres?
# 1. 功能的瑞士军刀
PostgreSQL的强大常常被低估,它早已不是传统的关系型数据库:
-- JSONB原生支持(带索引!)
SELECT * FROM products WHERE attributes->>'color' = 'red';
-- 全文搜索无需额外组件
SELECT to_tsvector('english', 'The quick brown fox') @@ to_tsquery('english', 'fox & quick');
-- 数组类型原生支持
SELECT * FROM users WHERE interests && ARRAY['hiking', 'coding'];
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 2. 扩展性生态
通过扩展,Postgres能变身多种数据库:
| 扩展名称 | 功能 | 适用场景 |
|---|---|---|
| TimescaleDB | 时序数据库 | 物联网监控 |
| PostGIS | 空间数据库 | 地理信息系统 |
| pg_graphql | GraphQL接口 | API快速开发 |
| pgvector | 向量数据库 | AI语义搜索 |
# 3. 事务的坚如磐石
# 实测:10万级并发写入的事务一致性
$ pgbench -c 100 -t 10000 -S
# 吞吐量: 45,234 tps
# 零数据不一致报告 🎯
1
2
3
4
2
3
4
# 实战场景:统一架构设计
# Web应用 + 缓存层
传统架构:
App → Redis → MySQL
1
极简架构:
-- 使用pg_cron实现自动缓存
CREATE EXTENSION pg_cron;
CREATE OR REPLACE FUNCTION refresh_cache()
RETURNS void AS $$
BEGIN
INSERT INTO cache_table (key, value)
SELECT id, jsonb_build_object(
'name', name,
'cache_time', NOW()
) FROM products
ON CONFLICT (key) DO UPDATE
SET value = EXCLUDED.value;
END;
$$ LANGUAGE plpgsql;
-- 每小时自动执行
SELECT cron.schedule('0 * * * *', $$SELECT refresh_cache()$$);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 实时分析系统
传统方案需要Kafka + Spark + ClickHouse,现在:
-- 使用LISTEN/NOTIFY实现事件流
LISTEN user_events;
-- 触发器捕获变更
CREATE TRIGGER user_activity
AFTER INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION pg_notify('user_events',
jsonb_build_object(
'user_id', NEW.id,
'event', CASE WHEN NEW.last_login > OLD.last_login THEN 'login' ELSE 'update' END,
'ts', NOW()
)::text
);
-- 消费端实时聚合
SELECT count(*)
FROM pg_notify_channel_stats('user_events')
WHERE event_time > NOW() - INTERVAL '1 hour';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 文档存储替代方案
-- 替代MongoDB的文档存储
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content JSONB NOT NULL,
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 原子操作
UPDATE documents
SET content = content || '{"tags": ["tech"]}'::jsonb
WHERE id = 123;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 极简主义的陷阱
当然,"一切皆用Postgres"不是银弹,我踩过的坑:
# 性能边界
- 大表全表扫描(>5000万行)时仍需分区
- 复杂OLAP查询可能需要列式存储
# 迁移成本
# 从MongoDB迁移的噩梦
$ mongodump --db myapp --collection logs
$ psql -c "CREATE EXTENSION mongo_fdw;"
$ psql -c "CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw OPTIONS (address 'mongo:27017', dbname 'myapp');"
1
2
3
4
2
3
4
# 团队认知
开发团队需要理解关系模型和JSONB的最佳实践,这比"NoSQL随便存"要求更高。
# 结语
经过两年的实践,我们的技术栈从7个数据库组件缩减到Postgres + 1个缓存层(其实还是PostgreSQL的表空间)。运维复杂度下降了70%,新功能开发速度提升了3倍。🚀
技术选型的终极目标不是炫技,而是让团队专注于业务创新。Postgres的"全能选手"特性,恰恰满足了现代应用对数据存储的复合需求。
当然,我并不鼓吹盲目使用Postgres——当你的需求明确是时序数据库或图数据库时,专用工具仍是更好的选择。但在大多数场景下,Postgres的灵活性和可靠性足以胜任。🏆
"当你只有一个锤子时,所有问题都像钉子"
——但至少这个锤子能修飞机引擎!
上次更新: 2026/01/28, 15:36:58