CodeGym /課程 /SQL SELF /陣列與 JSONB 的比較

陣列與 JSONB 的比較

SQL SELF
等級 36, 課堂 0
開放

今天我們要更深入了解陣列,然後把它跟 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 的優點

  • 超彈性。你可以隨時加 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 則看資料結構用 GIN 或 BTREE。

效能比較

一般查找任務,陣列會比較快。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。記得效能跟索引也要考慮進去啦!

2
任務
SQL SELF, 等級 36, 課堂 0
上鎖
使用陣列來儲存資料
使用陣列來儲存資料
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION