像我們現在做開發的時候,誰沒接觸過 JSON 呀,調用 Web API,保存配置文件,處理物聯網設備傳回的日誌之類的,JSON 這種半結構化數據真是隨處可見。
金倉數據庫 KingbaseES (KES) 在國產數據庫中屬於佼佼者,所以其功能自然不容忽視,該數據庫原本就具備 JSON 數據類型的相關支持,而且特意為我們供應了一整套實用的函數以及索引機制,大致來講,就是使得用户既能收穫關係型數據庫那值得信賴的 ACID 特性,又能夠輕鬆獲取 NoSQL 所具有的靈活性。
今天這篇文章,咱們來講講 KingbaseES 如何全方位支持 JSON 函數的,帶大家一起輕鬆應對半結構化數據。
1. 選型第一步:JSON 和 JSONB 到底用哪個?
在 KingbaseES 裏,存 JSON 數據有兩種路子,雖然看着都能存,但這倆在底層的脾氣秉性可大不一樣:
- JSON 類型:
- 特性:簡單粗暴,你給它啥樣,它就存啥樣。純文本存儲,連空格、鍵的順序、甚至重複的鍵都給你留着。
- 缺點:查起來費勁,每次都得重新解析一遍,效率不高,而且還沒法建索引。
- 適用場景:這就適合那些必須原封不動保留原始數據的情況,比如法律審計啊,或者單純當個日誌歸檔存着不動。
JSON 文本(鬆散、無序、帶空格)
{
"user_name": "張三",
"age": 28,
"is_vip": true,
"hobbies": ["編程", "遊戲", "閲讀"],
"address": {
"city": "北京",
"street": "科技園路8號"
},
"last_login": null,
"score": 95.5
}
- JSONB 類型(強烈推薦):
- 特性:存的是二進制格式。存進去的時候它會先“嚼碎”了(解析),把多餘的空格扔了,鍵的順序也不留,重複的鍵只留最後一個。
- 優點:查起來飛快,因為不需要再解析了;最關鍵的是,它支持 GIN 索引,這可是查詢性能起飛的關鍵。
- 適用場景:只要你是需要頻繁查、改、處理 JSON 數據,選它準沒錯。
JSONB 二進制結構(緊湊、有序、樹狀)
JSONB_OBJECT [8字節頭部]
├─ 鍵序1(S:字符串類型):"address" → 嵌套對象
│ ├─ 鍵序1:"city"(S)→ "北京"(16字節)
│ └─ 鍵序2:"street"(S)→ "科技園路8號"(24字節)
├─ 鍵序2(B:布爾類型):"is_vip" → true(1字節)
├─ 鍵序3(N:數字類型):"age" → 28(4字節,整數編碼)
├─ 鍵序4(A:數組類型):"hobbies" → 3個元素
│ ├─ 索引0(S):"編程"(8字節)
│ ├─ 索引1(S):"遊戲"(8字節)
│ └─ 索引2(S):"閲讀"(8字節)
├─ 鍵序5(N:數字類型):"score" → 95.5(8字節,浮點數編碼)
├─ 鍵序6(NULL:空類型):"last_login" → null(1字節)
└─ 鍵序7(S:字符串類型):"user_name" → "張三"(12字節)
2. 動手試試:從建表到查詢
光説不練假把式,咱們直接上代碼,看看 KES 的 JSON 能力到底怎麼樣。
2.1 先建個表,插點數據
咱們先搞一張表,裏面帶個 JSONB 類型的字段:
CREATE TABLE product_docs (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
attributes JSONB -- 使用 JSONB 類型
);
-- 插入數據
INSERT INTO product_docs (name, attributes) VALUES
('智能手機', '{"brand": "KingMobile", "color": "black", "specs": {"storage": "256GB", "ram": "12GB"}, "tags": ["new", "sale"]}'),
('藍牙耳機', '{"brand": "KingAudio", "color": "white", "specs": {"battery": "24h"}, "tags": ["wireless"]}');
2.2 像切菜一樣靈活的查詢操作符
KES 提供了一套跟 PostgreSQL 很像的操作符,取數據特別順手:
->: 拿對象(出來的還是 JSON 格式)。->>: 拿文本(出來的就是純字符串了)。#>: 按路徑拿對象(層級深的時候好用)。
-- 查詢所有品牌(返回文本)
SELECT attributes->>'brand' AS brand FROM product_docs;
-- 查詢存儲規格為 256GB 的產品(嵌套查詢)
SELECT name
FROM product_docs
WHERE attributes->'specs'->>'storage' = '256GB';
2.3 強大的標準 SQL JSON 函數
除了上面那些好用的操作符,KingbaseES 對 SQL 標準和 Oracle 風格 的 JSON 函數支持得也相當完美。如果你以前習慣用 Oracle,那上手肯定特親切。
- JSON_VALUE:取單個值。
- JSON_QUERY:取對象或者數組。
- JSON_TABLE:這個厲害了,能把 JSON 數據直接轉換成關係表的格式(行列轉換的神器)。
-- 使用 JSON_VALUE 提取顏色
SELECT name, JSON_VALUE(attributes, '$.color') AS color
FROM product_docs;
-- 使用 JSON_TABLE 將 JSON 數組拆解為行
-- 假設我們需要展開 tags 數組
SELECT p.name, t.tag
FROM product_docs p,
JSON_TABLE(p.attributes, '$.tags[*]' COLUMNS (tag VARCHAR(20) PATH '$')) AS t;
3. 進階玩法:修改與構建
3.1 直接在數據庫裏改 JSON
以前可能得把數據拿出來在代碼裏改,現在不用了,直接在數據庫這一層就能動刀:
- jsonb_set:更新指定路徑下的值。
- - :刪除鍵或數組元素。
-- 將 ID 為 1 的手機顏色修改為 "silver"
UPDATE product_docs
SET attributes = jsonb_set(attributes, '{color}', '"silver"')
WHERE id = 1;
-- 給所有產品增加一個 "in_stock" 標記
UPDATE product_docs
SET attributes = attributes || '{"in_stock": true}';
3.2 構造 JSON
有時候前端要 JSON 格式,咱們也不用在後端代碼裏拼了,直接把關係型數據轉成 JSON 吐出去:
-- 將查詢結果直接構建為 JSON 對象
SELECT jsonb_build_object(
'product_name', name,
'details', attributes
)
FROM product_docs;
4. 性能加速器:GIN 索引
這可是 JSONB 的“殺手鐗”。要是表裏 JSON 數據多了,全表掃描肯定慢得要死。這時候,KES 的 GIN (Generalized Inverted Index) 索引就派上用場了。
-- 在 attributes 列上創建 GIN 索引
CREATE INDEX idx_product_attrs ON product_docs USING GIN (attributes);
建好索引之後,像下面這種查詢,哪怕數據量到了千萬級,也能瞬間給你返回結果:
-- 查詢包含 "wireless" 標籤的產品
-- @> 是“包含”操作符,GIN 索引對此支持極佳
SELECT name FROM product_docs WHERE attributes @> '{"tags": ["wireless"]}';
5. 小結
總的來説,KingbaseES 對 JSON 的支持可不是簡單地“能存能取”那麼簡單,它其實是給咱們構建了一套完整的生態系統:
- 要麼存要麼用:JSON 和 JSONB 隨你挑。
- 兼容性強:既有簡單的操作符,也支持 Oracle/SQL 標準的那些函數(比如
JSON_TABLE),老項目遷移過來也省心。 - 性能卓越:配合 GIN 索引,查半結構化數據也能像查普通表一樣快。
不管你是想做一個靈活的內容管理系統(CMS),還是得處理那些變來變去的電商商品屬性,KingbaseES 的 JSON 能力都能給你穩穩的支撐。
參考資料:KingbaseES 數據庫知識庫