mysql在2015年的5.7以后,InnoDB存儲引擎已經開始對json數據進行支持,對json支持有如下優勢:
- JSON數據有效性檢查:BLOB類型無法在數據庫層做這樣的約束性檢查,如不合法會報錯:
- 查詢性能的提升:查詢不需要遍歷所有字符串才能找到數據
- 支持索引:通過虛擬列的功能可以對JSON中的部分數據進行索引
- 存儲的容量大,近似於LongBlob與LongText(4G)
建表語句:
CREATE TABLE `employe` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(18) DEFAULT NULL, `sex` int DEFAULT NULL, `others` json DEFAULT NULL, `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '錄入時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=42334 DEFAULT CHARSET=utf8mb4;
獲取JSON中的某個字段的風格與alibaba中fastjson中的JSONPath類似,但是功能與之相差甚遠:
- . 屬性訪問,例如$.name
- $ 根對象,即當前json
- * 對象的所有屬性,如:$.* ,當為JSONArray時,$.* 無效
其中支持json的主要函數如下表:或見https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html
簡單列一下常用操作,便於記憶:
- JSON_EXTRACT(column_name,'$.name')返回該json列column中的name中的值
- JSON_SEARCH(others, 'one', "露露") 若該字段存在,返回路徑,若不存在返回null:select * from employe where JSON_SEARCH(others, 'one', "露露") is not null;//查找存在“露露”的記錄;該方法中的中間參數有“one”與“all”兩種,one返回該json中第一次找到的記錄路徑,all返回該json中所有找到的路徑,即若存在多個“露露”則返回多個露露的路徑
- JSON_TYPE(others) 判斷alias的json類型(ARRAY或者OBJECT)
- JSON_VALID(others) 判斷alias 是否是一個合法的json
- JSON_CONTAINS(others, '露露', '$.alias');
- mysql5.7.9開始增加了一種簡寫方式:column->path; select others->'$.address' from employe 查詢json中的address列 類似:select JSON_EXTRACT(others, '$.address') from employe where id = 42332;
-
select json_contains('{"a":1,"b":4}','{"a":1}') 結果1
select json_contains('{"a":2,"b":1}','{"a":1}') 結果0
select json_contains('{"a":[1,2,3],"b":1}','[1,2]','$.a') 結果1。數組包含則需要所有元素都存在。
select json_contains('{"a":[1,2,3],"b":1}','1','$.a')
- select json_contains(others, '\"露露\"','$.alias') from employe; 使用json_contains的時候,如果是字符串要用雙引號包括,如果去掉雙引號則報錯。
虛擬列:虛擬列類似於視圖,將others字段中的address提取出來作為一個虛擬列address,當others字段中的address發生改變時,虛擬列會同時改變。
ALTER TABLE employe ADD address varchar(128) GENERATED ALWAYS AS (json_extract(others,'$.address')) VIRTUAL;

若去掉address列的引號可用replace替換:
ALTER TABLE employe ADD address varchar(128) GENERATED ALWAYS AS (REPLACE(json_extract(others,'$.address'),"\"",'')) VIRTUAL;
可對該虛擬字段進行查詢:
select * from employe where address="北京昌平";
在MySQL 5.7中,支持兩種generated column,即virtual generated column和stored generated column,前者只將generated column保存在數據字典中(表的元數據),並不會將這一列數據持久化到磁盤上;后者會將generated column持久化到磁盤上,而不是每次讀取的時候計算所得。很明顯,后者存放了可以通過已有數據計算而得的數據,需要更多的磁盤空間,與virtual column相比並沒有優勢,因此,MySQL 5.7中,不指定generated column的類型,默認是virtual column。
虛擬索引:虛擬列與普通列類似可創建索引,虛擬索引列也是通過傳統的B+樹索引即可實現對JSON格式部分屬性的快速查詢。使用方法是首先創建該虛擬列,然后在該虛擬列上創建索引:
alter table employe add INDEX add_index(address);
在創建索引后執行語句select * from employe where address="北京昌平";如下圖,發現使用到了索引:
效率問題:關於效率方面,使用json報錯或將json轉化為多表存儲的效率對比參考https://www.cnblogs.com/lkpnotice/p/6903187.html