CodeGym /课程 /SQL SELF /数组和JSONB的对比

数组和JSONB的对比

SQL SELF
第 36 级 , 课程 0
可用

数组和JSONB的对比

今天我们要更深入地理解数组,也要把它和JSONB做个全面对比,看看各自的优缺点,以及在实际项目里怎么用才最爽。

数组 vs JSONB:数据小乌龟 vs 灵活百宝箱

你应该已经知道,PostgreSQL里的数组只能存一种类型的数据:比如数字、字符串或者日期。举个例子:学生的成绩单,每个元素都是数字。

-- 学生和他们成绩的表
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT,
    grades INTEGER[]    -- 成绩数组
);

JSONB和数组不一样,它是以JSON结构存数据的。很像大家熟悉的JavaScript对象,但解析和索引都更快。JSONB可以存有序的列表,也可以存带key-value的对象。

-- 学生和各种信息的表
CREATE TABLE students_details (
    id SERIAL PRIMARY KEY,
    name TEXT,
    details JSONB  -- 灵活的JSON结构
);

JSONB里的数据例子:

{
    "grades": [90, 82, 77],
    "address": {
        "city": "Berlin",
        "zip": "352912"
    }
}

所以说,数组就是简单搞定一堆值的列表,而JSONB能玩出花来,适合复杂数据。

数组和JSONB的主要区别

特性 数组 JSONB
结构类型 线性数据结构 层级数据结构
元素类型 只能一种数据类型 可以多种数据类型
结构大小 固定(线性) 灵活,可以有列表和对象
访问速度 数据固定时很快 复杂查询时慢点
索引 索引支持很好 需要用GIN类型索引
应用场景 简单的值列表或数组 复杂数据:嵌套对象/列表

下面看看实际用起来是啥感觉。

什么时候用数组?

比如你有个图书数据库,每本书可以属于多个类型。这时候数组就很合适。

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    title TEXT,
    genres TEXT[]    -- 类型数组
);

-- 插入一本有多个类型的书
INSERT INTO books (title, genres)
VALUES ('1984', ARRAY['Dystopia', 'Political Fiction', 'Science Fiction']);

数组适合这些场景:

  • 你的数据就是纯列表,
  • 列表不大而且类型单一(比如字符串或数字),
  • 你只需要存和取列表(不搞花里胡哨的操作)。

数组的优点

  • 存同类型数据很简单。
  • 适合小型列表,比如标签、分类或评分。

什么时候用JSONB?

现在假设你想存更复杂的图书信息,包括类型、ISBN和评分。数组就不行了——这时候该上JSONB了。

CREATE TABLE books_details (
    id SERIAL PRIMARY KEY,
    title TEXT,
    details JSONB    -- 书的详细信息,JSONB格式
);

-- 插入一本书的复杂信息
INSERT INTO books_details (title, details)
VALUES (
    '1984',
    '{"genres": ["Dystopia", "Political Fiction", "Science Fiction"],
      "isbn": "9780451524935",
      "rating": 8.9}'
);

JSONB适合你需要:

  • 存复杂或多样化的数据(数字、字符串、列表、对象),
  • 动态加字段,不用改表结构,
  • 存嵌套数据(比如地址、属性、配置)。

JSONB的优点

  • 超灵活。想加啥key/value都行,不用动表结构。
  • 适合存复杂数据,比如API的JSON响应。

数组和JSONB怎么选?

只需要存同类型的列表——用数组。 比如:

-- 存活动参与者ID
CREATE TABLE events (
    id SERIAL PRIMARY KEY,
    participant_ids INTEGER[]
);

如果数据类型多样或结构复杂——用JSONB更好。 比如:

-- 存客户信息和地址
CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    info JSONB
);

数组和JSONB的索引方式不一样。 数组一般用GIN索引,JSONB可以用GINBTREE,看你数据结构咋样。

性能

数组在常规查找任务上更快。JSONB慢点,但胜在灵活。如果你只是查元素(比如类型或ID),数组会更快:

-- 用GIN索引搞数组
CREATE INDEX idx_genres ON books USING GIN(genres);

-- 按类型筛选书
SELECT * FROM books WHERE genres @> ARRAY['Science Fiction'];

数据存在性检查

JSONB在按key筛选时更强:

-- 检查有没有"genres"这个key
SELECT * FROM books_details WHERE details ? 'genres';

-- 检查列表里有没有某个元素
SELECT * FROM books_details WHERE details->'genres' ?| ARRAY['Fantasy', 'Dystopia'];

数组可以直接查值:

-- 检查数组里有没有某个元素
SELECT * FROM books WHERE genres @> ARRAY['Fantasy'];

结构的灵活性

如果你数据有复杂嵌套结构,JSONB就无敌了:

{
    "genres": ["Fantasy", "Adventure"],
    "ratings": {"goodreads": 8.5, "amazon": 4.7}
}

数组做不到,除非你搞表规范化或者加一堆字段。

总之,数组和JSONB不是互相竞争,而是各有用武之地。如果你的数据像个列表——用数组。如果数据复杂、嵌套或者类型多样——放心用JSONB。记得考虑性能和索引方式就行!

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION