MySQL 5.7.8以後原生JSON格式支持

在MySQL與PostgreSQL的對比中,PG的JSON格式支持優勢總是不斷被拿來比較。其實早先MariaDB也有對非結構化的數據進行存儲的方案,稱爲dynamic column,但是方案是通過BLOB類型的方式來存儲。這樣導致的問題是查詢性能不高,不能有效建立索引,與一些文檔數據庫對比,優勢並不大,故在社區的反應其實比較一般。當然,MariaDB的dynamic column功能還不僅限於非結構化數據的存儲,但不在本文進行展開。

MySQL 5.7.8版本開始InnoDB存儲引擎已經原生支持JSON格式,該格式不是簡單的BLOB類似的替換。原生的JSON格式支持有以下的優勢:

  • JSON數據有效性檢查:BLOB類型無法在數據庫層做這樣的約束性檢查
  • 查詢性能的提升:查詢不需要遍歷所有字符串才能找到數據
  • 支持索引:通過虛擬列的功能可以對JSON中的部分數據進行索引

 

官方文檔說明:

查看MySql版本

select version();

注意,最低需要MySql版本5.7.7版本以上。

選擇一個數據庫

 use db_admin;
 Database changed

創建一個表

create table user (uid int auto_increment,data json,primary key(uid))engine=innodb;
Query OK, 0 rows affected (0.04 sec)

插入數據

insert into user values(NULL,'{"name":"David","mail":"[email protected]","address":"BeiJin"}');
insert into user values (NULL,'{"name":"Amy","mail":"[email protected]"}');
insert into user values (NULL,'{"name":"Amy","mail":"[email protected]","age":[22,25]}');

可以看到我們新建了表user,並且將列data定義爲了JSON類型。這意味着我們可以對插入的數據做JSON格式檢查,確保其符合JSON格式的約束,如插入一條不合法的JSON數據會報如下錯誤:

insert into user values (NULL,"test");

查詢 JSON

查詢 json 中的數據用 column->path 的形式,其中對象類型 path 這樣表示 $.path, 而數組類型則是 $[index]

SELECT uid, data->'$.address', data->'$.name', data->'$.age[0]', data->'$.age[1]' FROM user;

可以看到對應字符串類型的 category->'$.name' 中還包含着雙引號,這其實並不是想要的結果,可以用 JSON_UNQUOTE 函數將雙引號去掉,從 MySQL 5.7.13 起也可以通過這個操作符 ->> 這個和 JSON_UNQUOTE 是等價的

select uid,data->'$.address',json_extract(data,'$.address'),JSON_UNQUOTE(data->'$.name'),data->>'$.name' from user;

創建索引

當然,最令人的激動的功能應該是MySQL 5.7的虛擬列功能,通過傳統的B+樹索引即可實現對JSON格式部分屬性的快速查詢。使用方法是首先創建該虛擬列,然後在該虛擬列上創建索引:

ALTER TABLE user ADD `user_name` varchar(128) GENERATED ALWAYS AS (json_extract(data,'$.name')) VIRTUAL; 
alter table user add index idx_username (user_name);

然後可以通過添加的索引對用戶名進行快速的查詢,這和普通類型的列查詢一樣。而通過explain可以驗證優化器已經選擇了在虛擬列上創建的新索引:

explain select * from user where user_name='"Amy"';

可以發現MySQL 5.7對於JSON格式堪稱完美,相信PostgreSQL陣營需要尋找新的策略來“攻擊”MySQL了吧。如無意外,還是會停留在優化器這塊,畢竟這塊是目前MySQL必須要克服的最大問題,好在MySQL團隊已經在重構優化器代碼,相信更好的優化器將會在下一個版本中全面爆發。而一大堆文檔數據庫們已經哭暈在廁所了吧。

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章