CodeGym /課程 /SQL SELF /處理 JSON 資料時常見的錯誤與避免方法

處理 JSON 資料時常見的錯誤與避免方法

SQL SELF
等級 34 , 課堂 4
開放

在 PostgreSQL 處理 JSON 資料超強大,但就像所有工具一樣,用的時候要小心。就算一點小錯誤,也可能讓你的查詢變成大謎題。 今天我們又要來聊聊在 PostgreSQL 處理 JSON 跟 JSONB 時常見的錯誤,還有怎麼避免它們。

問題 1:用 JSON 取代 JSONB

很多新手會誤以為 JSON 是存 JSON 資料最好的選擇。但其實在 PostgreSQL 裡,JSON 是用純文字存資料,這會讓你在搜尋或篩選時效能變超差。

錯誤範例:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSON
);

INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');

INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');

如果你想用 key (price) 來篩選,速度會比 JSONB 慢很多。

怎麼修正: 如果你打算常常篩選或查資料,直接用 JSONB 吧。

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

問題 2:JSONB 沒加 index

JSONB 超強大沒錯,但如果沒加 index,複雜查詢時效能會掉超多。

錯誤範例:假設我們有個欄位 details,裡面塞了一堆 JSON 物件:

SELECT * FROM products WHERE details->>'name' = 'Laptop';

如果沒加 index,server 會 full table scan(整張表慢慢找),超浪費時間。

怎麼修正: 加個 GIN index,查 key 會快很多:

CREATE INDEX idx_details_name ON products USING gin (details jsonb_path_ops);

問題 3:抓巢狀資料時出錯

從巢狀物件或 array 抓資料很容易搞混,尤其你還不熟 ->->> 這兩個 operator 的差別時。

錯誤範例:

SELECT details->'price' FROM products;

這個查詢會回傳 JSON 格式的值,不是純字串("1000" 而不是 1000)。如果你只想要值,要用 ->>

SELECT details->>'price' FROM products;

問題 4:operator 用錯

你可能看過 @> 這個 operator,覺得:「看起來很酷耶,來用用看!」但如果你不懂它怎麼運作,結果可能會很奇怪。

錯誤範例:

SELECT * FROM products WHERE details @> '{"price": 1000}';

這個查詢只有在 price 是數字時才會 work。如果值是字串 "1000",這查詢會找不到東西。

怎麼修正: 記得注意 JSON 裡的資料型別:

SELECT * FROM products WHERE details->>'price' = '1000';

問題 5:超大的 JSON 物件

沒優化就直接存很大的 JSON 物件,查詢速度會慢到爆。而且就算你只想改 JSONB 裡一小段資料,也要整個物件都處理一次。

怎麼修正: 如果有些 key 常常用,直接拉出來變成 table 的欄位。例如:

ALTER TABLE products ADD COLUMN price NUMERIC;
UPDATE products SET price = (details->>'price')::NUMERIC;

這樣你就可以有效率地篩選跟排序,不用每次都拆 JSONB。

問題 6:每次改資料都重建整個物件

jsonb_set()jsonb_insert() 這種 function 時,PostgreSQL 會重建一個全新的 JSONB 物件,這對效能來說很傷。

怎麼修正: 盡量減少 JSONB 的更新次數。例如,不要一直改同一個物件,把所有變動合併成一個 query:

UPDATE products
SET details = jsonb_set(details, '{price}', '1500'::jsonb);

問題 7:搞不懂 array 結構

JSONB 裡的 array 也要小心用。假設你有個 array:

{
    "tags": ["electronics", "laptop", "sale"]
}

你想查有沒有 "laptop" 這個 tag。如果 operator @> 用錯,可能查不到,因為它要的是 array,不是單一字串。

錯誤範例:

SELECT * FROM products WHERE details->'tags' @> '"laptop"';

怎麼修正: @> operator 要用正確格式:

SELECT * FROM products WHERE details->'tags' @> '["laptop"]';

避免錯誤的小建議

想在用 JSONB 時少踩雷,可以照這些建議做:

選對資料型別。 如果你資料量大又常常要篩選,記得用 JSONB,不要用 JSON

加 index。 如果常查某些 key,記得加對應的 index(像 GIN)。

插入前先檢查資料。 用 validation function 先檢查資料結構:

DO $$
BEGIN
    IF jsonb_typeof('{"price": 1000}'::jsonb->'price') IS DISTINCT FROM 'number' THEN
        RAISE EXCEPTION 'Price 必須是數字';
    END IF;
END $$;

優化資料結構。 如果有些 key 特別常用,直接拉出來變成 table 欄位。

多看 operator 跟 function。 仔細讀 PostgreSQL 官方文件,搞懂 ->->>@>?| 等等的差別。

JSON 跟 JSONB 可以讓你很彈性地處理複雜資料。重點是選對工具、避開常見錯誤,這樣你的 code 就又快又好維護啦!

1
問卷/小測驗
在 JSON 物件中更新資料,等級 34,課堂 4
未開放
在 JSON 物件中更新資料
在 JSON 物件中更新資料
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION