mysql 之 json 数据类型的使用及高效检索(配合虚拟列 virtual generated column)

硅谷漂流者
• 阅读 3842

mysql 5.7+ 版本开始支持 json 数据类型,可以方便的存储JSON格式的数据,同时配合虚拟列 (virtual generated column),可以方便的为 json 列数据的某属性映射虚拟列,建立索引,高效检索。

构造json数据

方法:json_array() / json_object()

json_array / json_object 用于组装 json 数据,json 说的简单些json就是由标量(int, float, string) + 数组 + 对象组合而成的,这两个函数可以方便的用于构造数组和对象的json格式串

json_array(item1, item2, item3, ...)
    =>
[item1, item2, item3]

json_object(key1, val1[, [key2, val2]...])
    => 
{"key1": "val1", "key2": "val2",...}

使用场景例如:

select json_object(
    "username", "big_cat",
    "favorites", json_array(
        json_object("article_id", 1, "favorited_at", "2019-01-18"),
        json_object("article_id", 2, "favorited_at", "2019-01-18"),
        json_object("article_id", 3, "favorited_at", "2019-01-18"),
        json_object("article_id", 4, "favorited_at", "2019-01-18")
    )
);
// result
{
    "username": "big_cat",
    "favorites": [
        {"article_id": 1, "favorited_at": "2019-01-18"},
        {"article_id": 2, "favorited_at": "2019-01-18"},
        {"article_id": 3, "favorited_at": "2019-01-18"},
        {"article_id": 4, "favorited_at": "2019-01-18"}
    ]
} 

读取json数据

方法:json_extract() /col->"$.{property_name}"

json_extract 用于读取 json 列的某字段,或者也可以使用 col->"$.{property_name}" 的方式访问

json_extract(`col`, '$.{property_name}') / `col`->'$.{property_name}'
create table `users` (
`id` int unsigned not null auto_increment primary key,
`doc` json
);

insert into `users`(`doc`)
values (json_object("name", "big_cat", "age", 28)), ('{"name": "james", "age": 29}');

select json_extract(`doc`, "$.name") as `name`, json_extract(`doc`, "$.age") as `age` from `users`;
select `doc`->"$.name" as `name`, `doc`->"$.age" as `age` from `users`;

高效检索json数据

mysql 提供的一些函数是可以方便我们条件检索json数据的,但无法使用索引,数据量大的时候难免低效。

select id, doc->"$.age" from users where json_extract(doc, "$.name") = "big_cat";
select id, doc->"$.age" from users where doc->"$.name" = "big_cat";

这时我们可以利用同 json 一同新增的特性:虚拟列(virtual generated column)。
将需要参与检索的 json 属性映射为 虚拟列,在虚拟列上建立索引,便可参与高效检索。

另外补充一下,在mysql 5.7+中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column。前者不存储元数据,后者会将 expression 的计算结果实际的存储下来。其实二者性能差距并不大,若对二者建立索引进行检索操作,前者性能可能会略低于后者,因为前者要对结果集即时的进行 expression 的演算,但后者需要消耗额外的存储空间。

需要注意的有:不存储数据的特性也导致只能在虚拟列上建立二级索引,插入数据时不可以向虚拟列插入数值(mysql自行负责演算)。

#虚拟列创建

ALTER TABLE `table_name` ADD COLUMN `col_name` <type> [ GENERATED ALWAYS ] AS ( <expression> ) [ VIRTUAL|STORED ]
[ UNIQUE [KEY] ] [ [PRIMARY] KEY ] [ NOT NULL ] [ COMMENT <text> ]
# 为 user 表的 json 字段的 name 创建虚拟列
alter table `users` add column `user_name` varchar(10) generated always as (`doc`->"$.name");
# 为虚拟列添加索引
alter table `users` add index `index_u_n`(`user_name`);
# 检索时可以使用索引
explain select `id`, `user_name`, `doc`->"$.age" as `age` from `users` where `user_name` = "big_cat" \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: NULL
         type: ref
possible_keys: index_u_n
          key: index_u_n
      key_len: 43
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

下面直接对 json 解析检索的方式是无法用到索引的

 explain select id from users where doc->"$.user_name" = "big_cat" \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)
explain select id from users where json_extract(`doc`, '$.username') = "big_cat" \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

还有其他 json 的使用这里就不说明了,大家可以参考一下文章:
mysql json 使用 类型 查询 函数:https://www.cnblogs.com/ooo0/...
MySQL 5.7 虚拟列 (virtual columns):https://www.cnblogs.com/raich...
MySQL 5.7原生JSON格式支持:https://www.cnblogs.com/zouca...

点赞
收藏
评论区
推荐文章
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
happlyfox happlyfox
4年前
Newtonsoft.Json的使用整理
关于我引言json是我们在工作中经常用到的一种数据传输格式,开始过程中解析json是我们经常面对的问题。NewtonsoftJson是c的一套json处理封装类,它可以高效,方便地帮助我们处理json。NetonSoftJson提供了完整的使用文档,文档地址如下:NetonSoftJson的不同使用场景常用方法序列化和反序列化这应该是我们最常用的俩
Peter20 Peter20
4年前
什么是索引?Mysql目前主要的几种索引类型
一、索引MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。创
Wesley13 Wesley13
3年前
MySQL Json函数(5.7以上)
oraclemysql5.7.8之后增加了对json数据格式的函数处理,可更加灵活的在数据库中操作json数据,如可变属性、自定义表单等等都使用使用该方式解决。在创建表时,可以使用“GENERATEDALWAYSAS”与json中的某个字段关联,并创建虚拟字段使json字符串也可以添加索引。创建测试json表
Wesley13 Wesley13
3年前
GSON搞定任何JSON数据
Gson介绍:GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。特点:a、快速、高效    b、代码量少、简洁c、面向对象d、数据传递和解析方便Gson的p
Wesley13 Wesley13
3年前
MySQL 5.7 使用原生JSON类型
首先回顾一下JSON的语法规则:数据在键值对中,数据由逗号分隔,花括号保存对象,方括号保存数组。按照最简单的形式,可以用下面的JSON表示:{"NAME":"Brett","email":"brett@xxx.com"}如何在MySQL中使用JSON类型:新建
Stella981 Stella981
3年前
Gson的学习与使用
Gson介绍:GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。特点:a、快速、高效b、代码量少、简洁c、面向对象d、数据传递和解析方便Gson的pom依赖:<d
Wesley13 Wesley13
3年前
JSON介绍
一、什么是JSON?JSON是一种轻量级的数据格式,一般用于数据交互。服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外)JSON的格式很像OC中的字典和数组{"name":"jack","age":10}{"names":\"jack","rose","jim"\}标准JSON格式的
Stella981 Stella981
3年前
Gson之实例五
前面四篇博客基本上可以满足我们处理的绝大多数需求,但有时项目中对json有特殊的格式规定.比如下面的json串解析:{"tableName":"students","tableData":{"id":1,"name":"李坤","birthDay":"Jun 22, 2012 9:54:49 PM"},{"id":2,"name":"曹贵生"
Wesley13 Wesley13
3年前
JSON,异步加载(学习笔记)
JSON是一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,json是用来数据传输的,前端与后端的数据通信)JSON是静态类(不需要构造),类似于Math,内部有各种函数   1).JSON.parse();stringjson(解析成对象属性和属性值,可以进行调用)  2).JSON.stringi
MYSQL中JSON类型介绍 | 京东物流技术团队
在mysql未支持json数据类型时,我们通常使用varchar、blob或text的数据类型存储json字符串,对mysql来说,用户插入的数据只是序列化后的一个普通的字符串,不会对JSON文档本身的语法合法性做检查,文档的合法性需要用户自己保证。在使用时需要先将整个json对象从数据库读取出来,在内存中完成解析及相应的计算处理,这种方式增加了数据库的网络开销并降低处理效率。
硅谷漂流者
硅谷漂流者
Lv1
衣带渐宽终不悔,为伊消得人憔悴。
文章
5
粉丝
0
获赞
0