在PostgreSQL里,很多开发者都会纠结:到底用啥数据结构存信息?用数组(ARRAY)来搞点简单结构?还是用文本(TEXT)字段存字符串?又或者,HSTORE存点“键-值”对?当然,还有个问题:到底啥时候用JSON或者JSONB才最合适?
为了帮你搞明白这些,我们来聊聊每种方式的优缺点,还会给你举点实际用法的例子。
啥时候用数组(ARRAY),啥时候用JSONB?
数组(ARRAY)超适合存一堆类型一样的数据。比如你有个学生分数列表,或者一条记录的标签,数组就很合适。
数组例子:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- 分数数组
);
INSERT INTO students (name, grades)
VALUES ('Alice', ARRAY[90, 85, 88]),
('Bob', ARRAY[70, 75, 78]);
另一方面,JSONB适合更复杂、嵌套的数据结构。比如你想给每条记录存点额外信息,比如每门课的分数描述,用JSONB就很香。
JSONB例子:
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- 分数相关的数据对象
);
INSERT INTO students_json (name, grades)
VALUES ('Alice', '{"数学": 90, "科学": 85, "英语": 88}'),
('Bob', '{"数学": 70, "科学": 75, "英语": 78}');
主要区别
| 对比项 | 数组(ARRAY) |
JSONB |
|---|---|---|
| 结构 | 同类型的简单数据 | 复杂嵌套数据结构 |
| 数据访问 | 按下标:grades[1] |
按键名:grades->'数学' |
| 索引支持 | 只能对整个数组用GIN或BTREE |
可以对键用GIN和BTREE索引 |
| 啥时候用 | 简单数据列表(标签、分数、ID) | 有键值的复杂对象 |
数组和JSONB互转例子
来看看怎么把数据在数组和JSONB之间互转:
数组 → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- 结果:
-- [{"90","85","88"}]
JSONB → 数组
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- 结果:
-- {90,85,88}
JSONB和文本数据(TEXT)对比
文本字段很适合你只想存点字符串或者小段没啥结构的数据。如果你就是想查查字符串,比如产品名、描述啥的,TEXT就够用了。
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('SQL基础', 'SQL的简明入门介绍'),
('高级PostgreSQL', 'PostgreSQL性能的深度指南');
啥时候更适合用JSONB?
如果你的字符串慢慢变成有嵌套结构的信息(比如描述里还带分类、标签列表),那还是用JSONB靠谱。
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "SQL基础", "tags": ["初学者", "数据库"]}'),
('{"title": "高级PostgreSQL", "tags": ["性能", "优化"]}');
主要区别
| 对比项 | 文本(TEXT) |
JSONB |
|---|---|---|
| 结构 | 无结构数据 | 有结构、可嵌套数据 |
| 查找 | 全文本搜索 | 按键、值、嵌套结构查找 |
| 数据修改 | 只能整体替换 | 可以改单个键 |
| 啥时候用 | 简单字符串 | 复杂的键值数据 |
JSONB和HSTORE对比
HSTORE算是JSONB的老大哥,可以存“键-值”对。比如你的数据结构很简单(不需要嵌套和数组),HSTORE会更轻便更快。
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"颜色"=>"红色", "尺码"=>"M"'),
('"颜色"=>"蓝色", "尺码"=>"L"');
为啥JSONB替代了HSTORE?
虽然HSTORE用来存“键-值”对很方便,但它不支持嵌套和数组,所以JSONB更万能。如果你数据结构变复杂了,JSONB就是自然而然的下一步。
主要区别
| 对比项 | HSTORE | JSONB |
|---|---|---|
| 结构 | “键-值”对,不支持嵌套 | 完整的嵌套结构 |
| 数组支持 | 不支持 | 支持 |
| 查找 | 只能按键查 | 按键、值、嵌套结构查 |
| 啥时候用 | 简单键值对 | 复杂数据结构 |
怎么选合适的数据类型?
如果你:
- 结构简单——就是列表或同类型数据,用数组(
ARRAY)。 - 就是字符串或描述,用文本字段(
TEXT)。 - “键-值”对但不需要嵌套,选
HSTORE。 - 有嵌套对象、数组、结构复杂——你需要JSONB。
格式互转例子
TEXT → JSONB
SELECT to_jsonb('简单文本例子') AS jsonb_form;
-- 结果: "简单文本例子"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- 结果: {"title": "SQL基础", "tags": ["初学者", "数据库"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- 结果: {"颜色": "红色", "尺码": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"颜色": "红色", "尺码": "M"}') AS hstore_form;
-- 结果: "颜色"=>"红色", "尺码"=>"M"
要注意啥?
如果你想要最大灵活性、支持复杂结构,选JSONB。不过,如果你的需求就是简单数据结构,比如数组、文本或“键-值”对,那就用对应的数据类型(ARRAY、TEXT、HSTORE)。
记住,选对数据结构能帮你后面开发省不少事,还能让你的查询更快!
GO TO FULL VERSION