PostgreSQL JSON 与 JSONB 类型查询详解:差异、示例与最佳实践
PostgreSQL JSON
和 JSONB
查询示例
PostgreSQL 支持 JSON
和 JSONB
两种 JSON 类型:
JSON
:存储为 纯文本,查询时需要解析,效率较低。JSONB
:存储为 二进制格式,支持索引,查询性能更好。
下面分别列出 JSON
和 JSONB
的查询示例。
一、JSON
查询示例
创建 JSON
类型的表:
CREATE TABLE demo_json (
id SERIAL PRIMARY KEY,
params JSON
);
插入数据:
INSERT INTO demo_json (params) VALUES
('{"name": "Alice", "age": 25, "is_active": true, "skills": ["Java", "SQL"], "address": {"city": "New York", "zip": 10001}, "salary": null}'),
('{"name": "Bob", "age": 30, "is_active": false, "skills": ["Python", "Go"], "address": {"city": "Los Angeles", "zip": 90001}, "salary": 5000}');
1. 查询 JSON 数据
(1) 查询 JSON 整个对象
SELECT params FROM demo_json;
(2) 查询 JSON 中的某个键
SELECT params->'name' FROM demo_json;
🔹 ->
返回 JSON
类型。
SELECT params->>'name' FROM demo_json;
🔹 ->>
返回 TEXT
类型(更适合查询)。
(3) 查询 JSON 数组中的元素
SELECT params->'skills'->0 FROM demo_json;
🔹 获取数组中的第一个元素。
2. 过滤 JSON 数据
(4) 查询 JSON 中包含某个值
SELECT * FROM demo_json WHERE params->>'name' = 'Alice';
(5) 查询 JSON 数字值
SELECT * FROM demo_json WHERE (params->>'age')::INT > 25;
(6) 查询 JSON 布尔值
SELECT * FROM demo_json WHERE (params->>'is_active')::BOOLEAN = true;
(7) 查询 JSON 中 null
值
SELECT * FROM demo_json WHERE params->>'salary' IS NULL;
3. JSON 不能索引,查询较慢
CREATE INDEX idx_json_name ON demo_json ((params->>'name'));
🔹 JSON
本身不支持索引,必须用 表达式索引 才能加速查询。
二、JSONB
查询示例
创建 JSONB
类型的表:
CREATE TABLE demo_jsonb (
id SERIAL PRIMARY KEY,
params JSONB
);
插入数据:
INSERT INTO demo_jsonb (params) VALUES
('{"name": "Alice", "age": 25, "is_active": true, "skills": ["Java", "SQL"], "address": {"city": "New York", "zip": 10001}, "salary": null}'),
('{"name": "Bob", "age": 30, "is_active": false, "skills": ["Python", "Go"], "address": {"city": "Los Angeles", "zip": 90001}, "salary": 5000}');
1. 查询 JSONB 数据
(1) 查询 JSONB 整个对象
SELECT params FROM demo_jsonb;
(2) 查询 JSONB 中的某个键
SELECT params->'name' FROM demo_jsonb;
SELECT params->>'name' FROM demo_jsonb;
🔹 区别:
->
返回JSONB
(适用于嵌套查询)。->>
返回TEXT
(适用于筛选)。
(3) 查询 JSONB 数组中的元素
SELECT params->'skills'->0 FROM demo_jsonb;
2. 过滤 JSONB 数据
(4) 查询 JSONB 中包含某个值
SELECT * FROM demo_jsonb WHERE params->>'name' = 'Alice';
(5) 查询 JSONB 数字值
SELECT * FROM demo_jsonb WHERE (params->>'age')::INT > 25;
(6) 查询 JSONB 布尔值
SELECT * FROM demo_jsonb WHERE (params->>'is_active')::BOOLEAN = true;
(7) 查询 JSONB 中 null
值
SELECT * FROM demo_jsonb WHERE params->>'salary' IS NULL;
3. JSONB 独有的高级查询
(8) 使用 @>
进行 JSONB 包含查询
SELECT * FROM demo_jsonb WHERE params @> '{"age": 25}';
🔹 查询 params
是否包含 {"age": 25}
。
(9) 查询 JSONB 数组是否包含某个值
SELECT * FROM demo_jsonb WHERE params->'skills' ? 'Java';
🔹 ?
用于数组包含查询。
(10) 查询 JSONB 数组是否包含多个值
SELECT * FROM demo_jsonb WHERE params->'skills' ?| array['Java', 'Python'];
🔹 ?|
表示包含至少一个。
SELECT * FROM demo_jsonb WHERE params->'skills' ?& array['Java', 'SQL'];
🔹 ?&
表示包含所有。
4. JSONB 更新
(11) 更新 JSONB 的某个值
UPDATE demo_jsonb
SET params = jsonb_set(params, '{age}', '40')
WHERE params->>'name' = 'Alice';
🔹 更新 age
字段为 40
。
(12) 更新 JSONB 中的嵌套对象
UPDATE demo_jsonb
SET params = jsonb_set(params, '{address, city}', '"Chicago"')
WHERE params->>'name' = 'Alice';
🔹 更新 address.city
为 Chicago
。
5. JSONB 索引(查询更快)
CREATE INDEX idx_jsonb_name ON demo_jsonb USING GIN (params);
🔹 JSONB 支持 GIN 索引,加速查询!
总结
对比项 | JSON | JSONB |
---|---|---|
存储格式 | 纯文本 | 二进制 |
查询性能 | 解析时才转换,较慢 | 直接查询,较快 |
索引支持 | 仅支持表达式索引 | 支持 GIN 索引 |
包含查询 | params->>'name' = 'Alice' | params @> '{"name": "Alice"}' |
更新单个键 | 需更新整个 JSON | jsonb_set() 可更新部分 |
数组查询 | 不支持 ? 操作符 | 支持 params->'skills' ? 'Java' |
🔹 JSONB
更适用于查询频繁的数据,尤其是带索引的查询。
🔹 JSON
适用于存储但不做复杂查询的数据。
🚀 结论:如果要查询 JSON 数据,推荐使用 JSONB
!