CodeGym /課程 /SQL SELF /比較 JSON 跟 JSONB:各自的優缺點

比較 JSON 跟 JSONB:各自的優缺點

SQL SELF
等級 33, 課堂 1
開放

JSON 跟 JSONB 最大的差別之一就是資料儲存的格式。JSON 是把資料存成純文字,JSONB 則是存成二進位格式。意思就是:

  • JSON 會把你傳進來的資料原封不動存起來。比如你插入 {"title": "PostgreSQL", "tags": ["database", "SQL"]} 這個字串,它就會照原樣存下去。
  • JSONB 則是先 parse 一下 JSON 物件,把多餘的空白去掉、把 key 排好順序、優化結構,然後才存成二進位格式。

這樣的優化讓 JSONB 在處理資料時,尤其是複雜的查詢、篩選、搜尋、排序時會快很多。

讀寫效能比較

JSON 跟 JSONB 在讀寫速度上有不同的特性:

  • JSON 寫入資料庫會比較快,因為不用先 parse 資料就能直接存。但讀取跟處理這些資料時會比較慢,因為 PostgreSQL 查詢時還要再 parse 一次。
  • JSONB 寫入時會慢一點,因為存之前要先處理資料。不過讀取、篩選、抓值都會快很多,所以如果你要做分析或搜尋,JSONB 會比較適合。

舉個例子:

-- 建立 JSON 跟 JSONB 的資料表
CREATE TABLE json_example (data JSON);
CREATE TABLE jsonb_example (data JSONB);

-- 插入資料
INSERT INTO json_example VALUES ('{"key": "值", "tags": ["json", "例子"]}');
INSERT INTO jsonb_example VALUES ('{"key": "值", "tags": ["jsonb", "例子"]}');

-- 篩選資料
SELECT * FROM json_example WHERE data->'key' = '"值"';  -- 比較慢
SELECT * FROM jsonb_example WHERE data->'key' = '"值"'; -- 比較快

資料索引

JSONB 最大的優點之一就是支援索引。PostgreSQL 可以幫 JSONB 欄位建立索引,用 GIN 這種索引型態。這樣搜尋跟篩選資料會快超多。

建立索引的範例:

-- 在 JSONB 欄位上建立索引
CREATE INDEX idx_jsonb_tags ON jsonb_example USING gin (data->'tags');

反過來說,JSON 是不支援索引的,所以如果你要做複雜的搜尋或篩選,JSON 就沒那麼適合。

什麼時候用 JSON,什麼時候用 JSONB

JSON 比較適合這幾種情境:

  • 你想要把資料原封不動存下來,不想被改動。
  • 你不打算常常對 JSON 資料做篩選、搜尋或排序。
  • JSON 資料主要是要傳給其他系統或前端,格式不能變(比如 API 回傳給前端)。

範例:

-- 純粹儲存 JSON,不做分析
CREATE TABLE api_responses (
    id SERIAL PRIMARY KEY,
    response JSON
);

-- 插入 API 回傳的資料
INSERT INTO api_responses (response)
VALUES ('{"status": "成功", "payload": {"id": 123, "name": "John"}}');

JSONB 適合這些情境:

  • 你會常常根據 JSON 裡面的值做篩選、搜尋、分組或排序。
  • 你比較在意讀取效能,不太在意寫入速度。
  • 你想要用索引來加速 JSON 資料的操作。

範例:

-- 用 JSONB 儲存資料,方便分析跟操作巢狀物件
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

-- 插入資料
INSERT INTO products (details)
VALUES ('{"name": "筆電", "price": 1200, "tags": ["電子產品", "電腦"]}');

-- 搜尋有 "電子產品" 標籤的商品
SELECT * FROM products
WHERE details @> '{"tags": ["電子產品"]}';

關於 @> 跟 --> 這些 operator 的用法,之後的講座還會再講 :P

JSON 跟 JSONB 的操作範例

我們來建立兩個資料表:一個用 JSON 欄位,一個用 JSONB:

CREATE TABLE json_table (
    id SERIAL PRIMARY KEY,
    data JSON
);

CREATE TABLE jsonb_table (
    id SERIAL PRIMARY KEY,
    data JSONB
);

插入資料的方式兩個表都一樣:

INSERT INTO json_table (data)
VALUES ('{"key": "值", "tags": ["json", "例子"]}');

INSERT INTO jsonb_table (data)
VALUES ('{"key": "值", "tags": ["jsonb", "例子"]}');

現在我們來查找 key 是 值 的資料:

-- 查 JSON
SELECT * FROM json_table
WHERE data->>'key' = '值';

-- 查 JSONB
SELECT * FROM jsonb_table
WHERE data->>'key' = '值';

如果資料量不大,效能差異其實感覺不太出來。但如果你有幾百萬筆資料,JSONB 的效能會好很多,尤其是你有建立索引的話:

CREATE INDEX idx_jsonb_key ON jsonb_table USING gin ((data->>'key'));

處理巢狀物件跟陣列,JSONB 也比較有效率:

-- 從陣列抓第一個 tag
SELECT data->'tags'->>0 AS first_tag 
FROM jsonb_table;

優缺點總結

特性 JSON JSONB
資料儲存 原封不動存成純文字 存成二進位格式,key 會排序
寫入效能 比較快,因為直接存原始資料 比較慢,因為要先 parse
讀取效能 比較慢,查詢時要 parse 比較快,已經優化好可以直接讀
索引 不支援 支援(GIN、BTREE 索引)
篩選 慢 快
操作支援 有限 功能多

到底要選 JSON 還是 JSONB,其實看你的需求。如果你只是想把資料原封不動存下來,選 JSON 就對了。如果你會常常對資料做篩選、搜尋、分組,JSONB 會更快更方便。

如果你的應用很複雜,JSON 資料不只是「存著而已」,還會拿來做分析,JSONB 絕對是你的好幫手。所以如果你猶豫的話,直接選 JSONB 吧!說不定你未來的「人生最快查詢」會感謝你現在的選擇!

2
任務
SQL SELF, 等級 33, 課堂 1
上鎖
插入與提取 JSON 和 JSONB 資料
插入與提取 JSON 和 JSONB 資料
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION