第 3 章 · 数据类型详解

PostgreSQL 「类型即竞争力」—— JSONB 操作符沙盒、char/varchar/text 性能图表、范围类型时间轴可视化

JSONB 操作符可视化

左侧编辑 JSON 文档,右侧选择操作符并填写参数,命中的路径会被 黄色高亮,路径上的祖先节点会被 蓝色高亮

JSON 文档

操作符 / 参数

结果

请选择一个操作符

等价 SQL

--

文档树(高亮命中)

说明:本沙盒在浏览器内模拟 PG 的 JSONB 操作符语义,仅用于教学。 真实 PG 行为以官方文档为准(如 ? 只匹配顶层 key、@> 是结构性包含等)。

char(n) vs varchar(n) vs text 性能 Benchmark

PG 中三者底层几乎一样,但 char(n) 会用空格补齐到 n 字符,浪费空间。下方图表为模拟数据,展示「写入耗时」「磁盘占用」「索引查询耗时」的相对差异。

字符串长度上限 n = 实际写入字符数 =
char(n) varchar(n) text
结论:当「实际字符数 < n」时,char(n) 的占用恒等于 n,而 varchar/text 只占实际字符数 + 1~4 字节头。 在 PG 里查询性能三者几乎一致,推荐默认用 text

范围类型:会议室时间轴 + 冲突检测

蓝、绿、黄三段是已有预订;输入「申请时段」按下检测按钮,红色虚线框就是新申请。冲突时框会闪烁。

起 (小时)
尚未检测

等价 SQL

SELECT * FROM bookings
WHERE period && tstzrange('14:00', '16:00');
下一章我们会用 EXCLUDE USING gist (period WITH &&) 让 PG 在 INSERT 时直接拒绝冲突预订。

类型选型速查

需求PG 推荐类型对应 MySQL关键提示
整数主键,单库bigint GENERATED ALWAYS AS IDENTITYBIGINT AUTO_INCREMENTPG 10+ 推荐用 IDENTITY 替代 SERIAL
分布式 / 离线 IDuuid (v7) / 雪花 IDBINARY(16)v4 随机 UUID 写入差,生产建议 v7
金额numeric(12, 2)DECIMAL(12, 2)千万别用 real / double / money
字符串字段text + CHECKVARCHAR(n)PG 三类型几乎一样,text 最灵活
时间戳(业务时刻)timestamptzTIMESTAMP (4 字节, 2038 问题)不带时区永远是坑
布尔booleanTINYINT(1)PG 是真布尔,三值逻辑
多标签text[] + GINJSON / 关联表查询用 @> &&
半结构化文档jsonb + GINJSONjsonb_path_ops 索引更小
时间区间 / 价格区间tstzrange / numrange(自行用两列 + 应用判断)配合 EXCLUDE 实现「不重叠」
固定枚举CREATE TYPE ... AS ENUMENUM('a','b')不能删值,会变需求改用关联表
IP 地址inet / cidrINT UNSIGNED + INET_ATON原生支持 IPv6 + 网段判断

JSONB 操作符速查

操作符含义示例
->按 key/index 取「JSON 子对象」payload -> 'device'
->>按 key/index 取「文本」payload ->> 'user_id'
#>按路径取 JSON 子对象payload #> '{device,os}'
#>>按路径取文本payload #>> '{device,ver}'
@>是否「包含」右侧payload @> '{"user_id":1}'
?顶层是否存在 keypayload ? 'items'
?|顶层存在任一 keypayload ?| ARRAY['a','b']
?&顶层存在所有 keypayload ?& ARRAY['a','b']
||合并(同 key 后者覆盖)p || '{"x":1}'
-删除 key 或下标p - 'a'