CodeGym /課程 /SQL SELF /JSON 跟其他型別比較: ARRAYTEXT、 <...

JSON 跟其他型別比較: ARRAYTEXTHSTORE

SQL SELF
等級 34 , 課堂 3
開放

在 PostgreSQL 裡,很多工程師都會遇到一個問題:到底該用哪種資料結構來存資料?要用 array(ARRAY)來存比較單純的資料?還是用 text(TEXT)欄位來存字串?又或者,HSTORE 來存「鍵-值」對?當然,還有一個問題:什麼時候該用 JSON 或 JSONB 呢?

為了幫你搞懂這些,我們會聊聊每種方式的優缺點,還有給你一些實際用法的例子。

什麼時候該用 array(ARRAY),什麼時候該用 JSONB?

ArrayARRAY)超適合存一堆同樣型別的資料。像是你有一個學生的分數清單,或是一個紀錄的標籤,array 就很剛好。

Array 範例:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT,
    grades INTEGER[] -- 分數 array
);

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(ARRAY JSONB
結構 同一型別的資料 複雜巢狀資料結構
資料存取 用 index:grades[1] 用 key:grades->'數學'
索引支援 只能對整個 array 用 GINBTREE 可以針對 key 用 GINBTREE 索引
什麼時候用 簡單的資料清單(標籤、分數、ID) 有 key 跟 value 的複雜物件

Array 跟 JSONB 互轉範例

來看看怎麼把資料從 array 轉成 JSONB,或反過來:

Array → JSONB

SELECT to_jsonb(grades) AS grades_jsonb
FROM students;

-- 結果:
-- [{"90","85","88"}]

JSONB → Array

SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- 結果:
-- {90,85,88}

JSONB 跟 text(TEXT)資料比較

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(TEXT JSONB
結構 沒結構的資料 有結構、巢狀資料
搜尋 全文字搜尋 可以用 key、value、巢狀結構搜尋
資料修改 只能整個換掉 可以只改某個 key
什麼時候用 單純的字串 複雜的 key-value 資料

JSONB 跟 HSTORE 比較

HSTORE 算是 JSONB 的前輩,可以存「鍵-值」對。像是你的資料結構很簡單(不需要巢狀或 array),HSTORE 會比較輕巧又快。

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    attributes HSTORE
);

INSERT INTO products (attributes)
VALUES ('"顏色"=>"紅", "尺寸"=>"M"'),
       ('"顏色"=>"藍", "尺寸"=>"L"');

為什麼 JSONB 取代了 HSTORE

雖然 HSTORE 很方便存「鍵-值」對,但它不支援巢狀跟 array,所以 JSONB 更萬用。如果你的資料已經不只是單純物件,JSONB 就是下一步啦。

主要差異

比較項目 HSTORE JSONB
結構 「鍵-值」對,沒巢狀 完整巢狀結構
Array 支援 沒有
搜尋 只能用 key 搜尋 可以用 key、value、巢狀結構搜尋
什麼時候用 簡單的鍵-值 複雜資料結構

怎麼選資料型別?

如果你:

  • 結構很簡單 — 清單或同型資料,就用 array(ARRAY
  • 單純字串或描述,就用 text 欄位(TEXT
  • 沒巢狀的「鍵-值」對,就選 HSTORE
  • 有巢狀物件、array、複雜資料結構 — 你要 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 或「鍵-值」對,就用對應的資料型別(ARRAYTEXTHSTORE)。

記得,選對資料結構可以讓你之後開發省很多麻煩,查詢效能也會更好!

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION