KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
PostgreSQL 应用课 · 课程导读 — keel 龙骨
PostgreSQL 应用课:把 PG 的特性用对 的参考信息:PostgreSQL 应用课 · 课程导读
你现在的起点
- 能写业务 SQL,会建表,也知道该加索引;
- 但类型是照着「别人都这么写」选的,约束是照着「ORM 自动生成的」加的;
- 遇到过「数据对不上」「查询少了行」「并发下数据被覆盖」,最后靠改代码绕过而不是靠改数据库解决;
- 听说过
EXPLAIN,但只在被逼急了才打开。
如果你中了三条以上,这门课是为你写的。
它不从「什么是关系型数据库」讲起,也不讲存储引擎内部——那些在《PostgreSQL 工程课》。本课只处理一件事:同样一个业务需求,PG 提供了好几种表达方式,怎么选、选了之后会付什么代价。
一条能走通的学习路径
先把类型和 NULL 的语义搞对(第 00 章)
→ 让约束替你在并发下兜底(第 01 章)
→ 判断 JSONB 什么时候是解、什么时候是债(第 02 章)
→ 把该在 SQL 里做的事从应用层搬回去(第 03 章)
→ 划清事务边界,选对并发写的表达方式(第 04 章)
→ 把权限与租户隔离下沉到数据库(第 05 章)
→ 承认边界:什么时候该换一套存储(第 06 章)
七章共享一张业务表:一个简化的订单/库存模型。第 00 章选的类型,第 02 章会被塞进 JSONB 讨论,第 04 章的并发场景直接建立在它上面,第 06 章用它来对比「拆列存」与「文档存」。
章节地图
| 章 | 关键问题 | 你会亲手验证什么 |
|---|---|---|
| 00 类型与建模 | 金额用什么类型、时间戳选哪种、NULL 为什么会静默漏行 | float8 与 numeric 累加 100 万次后的真实差值;同一行在 Asia/Shanghai 与 UTC 下读出来的不同 |
| 01 约束是数据库兜底 | 唯一约束在并发下能挡住什么、ON CONFLICT 的返回语义、外键的代价 |
两个会话同时插同一唯一键,抄下 23505 全文;部分唯一索引如何实现「软删除后 code 可复用」 |
| 02 JSONB 的边界 | 什么时候该用 JSONB、GIN 索引加速的是什么、为什么 ->> 用不上索引 |
20 万行上 @> 查询从顺序扫描 2470 缓冲降到位图索引 204 缓冲的全过程 |
| 03 把逻辑压进 SQL | 相关子查询为什么是 N+1 的 SQL 版、窗口函数替代自连接、CTE 什么时候会物化 | 同一需求的三种写法计划对比;CTE 内联与 MATERIALIZED 的计划差异;2 万行两种写法的耗时 |
| 04 事务边界与并发写 | 事务该包多大、乐观锁和悲观锁怎么选、SKIP LOCKED 为什么能做队列 |
制造一次真阻塞并读出 pg_blocking_pids;复现读已提交下的丢失更新;两个消费者用 SKIP LOCKED 分食 5 个任务 |
| 05 权限、schema 与租户隔离 | 最小权限怎么给、search_path 会怎么害你、RLS 能挡到哪一层 |
建角色后越权被拒的真实报错;序列权限与表权限分开的坑;RLS 在同表多租户下的实际过滤 |
| 06 选型与边界 | 模糊搜索上了什么索引、JSONB 相比拆列表少了什么、什么时候该换存储 | pg_trgm 在 ASCII 与汉字上的两种命运;show_trgm 返回空集与集群 locale 的因果 |
学完这门课你能做什么
- 拿到一张对账对不上的告警,先去看金额列的类型,而不是先怀疑代码;
- 拿到一个「唯一性偶尔失效」的报障,能判断是应用层判重还是数据库约束,并知道约束在并发下的真实语义;
- 拿到一个慢的模糊搜索,能说清前缀匹配和包含匹配分别需要什么索引,以及为什么你那台机器的中文搜索没生效;
- 在写「取库存、扣减」这类代码时,能说出三种并发表达的代价,并知道哪种在哪个冲突率下更划算;
- 在设计多租户表时,能判断隔离该放在数据库(RLS)还是应用层,以及各自的失效模式。
与相邻课程的分工
| 问题 | 去哪门课 |
|---|---|
| 这条 SQL 为什么慢、该加什么索引、连接池开多大、缓存怎么设计 | 《数据库与缓存调优》 |
| 表为什么越用越大、崩溃后数据为什么还在、备库为什么读不到刚写的表 | 《PostgreSQL 工程课》 |
| 该用 Postgres 还是 Mongo、pgvector 能不能顶掉专用向量库 | 本课第 06 章,深挖见《向量数据库工程课》 |
| 消息不丢不重、队列怎么选 | 《Kafka 工程课》 与《RabbitMQ 工程课》 |
两门 PG 课的结论不冲突,但解释同一个现象的角度不同。同一个「并发更新出错」,本课关心的是「你的代码该怎么写」,工程课关心的是「行锁记在哪、快照怎么判可见」。混用两边的解释是最容易犯的错。
前置要求
- 会基本的 SQL 与
psql,能看懂EXPLAIN的输出形状; - 建议先读《数据库与缓存调优》,建立索引与事务的通用概念;
- 本课所有实验都在一台本地 PostgreSQL 16.15 上跑,正文会给出建表和造数语句,你可以完整复现;
- 能读英文报错原文。本课的报错一律不翻译,因为真实排查时你面对的也是原文。