左侧编辑 JSON 文档,右侧选择操作符并填写参数,命中的路径会被 黄色高亮,路径上的祖先节点会被 蓝色高亮。
? 只匹配顶层 key、@> 是结构性包含等)。PG 中三者底层几乎一样,但 char(n) 会用空格补齐到 n 字符,浪费空间。下方图表为模拟数据,展示「写入耗时」「磁盘占用」「索引查询耗时」的相对差异。
char(n) 的占用恒等于 n,而 varchar/text 只占实际字符数 + 1~4 字节头。
在 PG 里查询性能三者几乎一致,推荐默认用 text。蓝、绿、黄三段是已有预订;输入「申请时段」按下检测按钮,红色虚线框就是新申请。冲突时框会闪烁。
SELECT * FROM bookings
WHERE period && tstzrange('14:00', '16:00');
EXCLUDE USING gist (period WITH &&) 让 PG 在 INSERT 时直接拒绝冲突预订。| 需求 | PG 推荐类型 | 对应 MySQL | 关键提示 |
|---|---|---|---|
| 整数主键,单库 | bigint GENERATED ALWAYS AS IDENTITY | BIGINT AUTO_INCREMENT | PG 10+ 推荐用 IDENTITY 替代 SERIAL |
| 分布式 / 离线 ID | uuid (v7) / 雪花 ID | BINARY(16) | v4 随机 UUID 写入差,生产建议 v7 |
| 金额 | numeric(12, 2) | DECIMAL(12, 2) | 千万别用 real / double / money |
| 字符串字段 | text + CHECK | VARCHAR(n) | PG 三类型几乎一样,text 最灵活 |
| 时间戳(业务时刻) | timestamptz | TIMESTAMP (4 字节, 2038 问题) | 不带时区永远是坑 |
| 布尔 | boolean | TINYINT(1) | PG 是真布尔,三值逻辑 |
| 多标签 | text[] + GIN | JSON / 关联表 | 查询用 @> && |
| 半结构化文档 | jsonb + GIN | JSON | jsonb_path_ops 索引更小 |
| 时间区间 / 价格区间 | tstzrange / numrange | (自行用两列 + 应用判断) | 配合 EXCLUDE 实现「不重叠」 |
| 固定枚举 | CREATE TYPE ... AS ENUM | ENUM('a','b') | 不能删值,会变需求改用关联表 |
| IP 地址 | inet / cidr | INT UNSIGNED + INET_ATON | 原生支持 IPv6 + 网段判断 |
| 操作符 | 含义 | 示例 |
|---|---|---|
-> | 按 key/index 取「JSON 子对象」 | payload -> 'device' |
->> | 按 key/index 取「文本」 | payload ->> 'user_id' |
#> | 按路径取 JSON 子对象 | payload #> '{device,os}' |
#>> | 按路径取文本 | payload #>> '{device,ver}' |
@> | 是否「包含」右侧 | payload @> '{"user_id":1}' |
? | 顶层是否存在 key | payload ? 'items' |
?| | 顶层存在任一 key | payload ?| ARRAY['a','b'] |
?& | 顶层存在所有 key | payload ?& ARRAY['a','b'] |
|| | 合并(同 key 后者覆盖) | p || '{"x":1}' |
- | 删除 key 或下标 | p - 'a' |