文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Mysql存储json格式数据需要掌握的

2023-10-11 18:30

关注

目录

一、前言

最近做的一个 填报项目,由于填报的字段比较多于是便在数据库当中使用了longtext类型的字段直接存储json数据。

为什么选择直接存储json数据?

  1. 业务比较复杂,涉及到很多 一对多 的多表关联,假如拆分存到各个业务表,那么每次查询修改是非常繁琐的,存储json一张表即可解决。
  2. 字段全部由前端来定,减少了前后端联调时间。
  3. 避免填报内容需求频繁调整而不断修改数据库结构,比如加字段,减字段这些都是经常有的事,完全可以让前端全权负责,你存什么我就给你返回什么。

但是这里我也是有一点好奇,既然存储为json,为什么不直接将字段类型设置为json?由于最近经常会用到数据库存json串,也是下定决心彻底把这块相关的知识给梳理一遍。

从5.7开始,MySQL开始支持json类型,用于存储JSON数据。关于json类型,mysql官网介绍以及使用,本篇文章也是重点整理的官网相关知识:https://dev.mysql.com/doc/refman/8.0/en/json.html

在这里插入图片描述

json数据类型提供了以下优势:

  1. 插入数据的时候自动验证数据是否是标准的json数据格式,如果不是会报异常!假如使用longtext存储json并不会有这种校验。

在这里插入图片描述

  1. 优化存储格式。存储在json列中的JSON文档被转换为内部格式,允许对文档元素进行快速读取访问。可以直接通过键或数组索引查找子对象或嵌套值,而无需读取json中所有值。

在这里插入图片描述

注意:

  1. 存储在JSON列中的任何JSON文档的大小都受限于最大允许的数据包系统变量的值,可以使用JSON_STORAGE_SIZE()获取到json长度
  2. 在MySQL 8.0.13之前,JSON列不能有非null的默认值。
  3. 存储JSON文档所需的空间与LONGBLOB或LONGTEXT大致相同
  4. Json类型不支持索引,但是可以在Json当中的列上使用索引!在MySQL 8.0.17及以后的版本中,InnoDB存储引擎支持JSON数组上的多值索引。
  5. MySQL优化器还会在匹配JSON表达式的虚拟列上寻找兼容的索引。
  6. 在MySQL 8.0中,MySQL 优化器可以对JSON列执行局部就地更新,而不是删除旧文档并将整个新文档写入该列。(在后面会重点讲解这一部分)

二、什么是 JSON

JSON 是 JavaScript Object Notation(JavaScript 对象表示法)的缩写,是一个轻量级的,基于文本的,跨语言的数据交换格式。易于阅读和编写。

JSON 的基本数据类型如下:

  1. 数值:十进制数,可以为负数或小数。
  2. 字符串:字符串是由双引号""包围的任意数量Unicode字符的集合,特殊符号使用反斜线转义。
  3. 布尔值:true,false。
  4. 数组:一个由零或多个值组成的有序序列。每个值可以为任意类型。数组使用方括号[] 括起来,元素之间用逗号,分隔。譬如:
 [1, "abc", null, true, "10:27:06.000000", {"id": 1}]
  1. 对象:一个由零或者多个键值对组成的无序集合。其中键必须是字符串,值可以是对象、数组、数字、字符串或者三个字面值(false、null、true)中的一个。值中的字面值中的英文必须使用小写。
    对象使用花括号{}括起来,键值对之间使用逗号 , 分隔,键与值之间用冒号 : 分隔。譬如:
 {"name": "John Doe", "age": 18, "address": {"country" : "china", "zip-code": "10000"}}
  1. 空值:null。

一些合法的JSON的实例:

{"a": 1, "b": [1, 2, 3]}[1, 2, "3", {"a": 4}]3.14"plain_text"

JSON 与 JS 对象的关系
很多人搞不清楚 JSON 和 JS 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。如

var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

JSON 和 JS 对象互转

要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}

要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'

简单地说,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在网络或者程序之间轻松地传递这个字符串,并在需要的时候将它还原为各编程语言所支持的数据格式,例如在 Java中,可以将 JSON 还原为数组或者一个基本对象。

XML本质上也可以作为跨语言的数据交换格式,JSON和XML的可读性可谓不相上下,一边是简易的语法,一边是规范的标签形式,很难分出胜负。

三、Mysql当中json函数

https://blog.csdn.net/weixin_43888891/article/details/130431272

四、JSON值部分更新

4.1.使用 Partial Updates 的条件

在MySQL 8.0中,优化器可以对JsoN列执行局部就地更新,而不是删除旧文档并将整个新文档写入该列。此优化可以在满足以下条件的更新中执行:

JSON_STORAGE_FREE(更新后释放的空间)

返回值:

创建测试表

mysql> CREATE TABLE jtable (jcol JSON);Query OK, 0 rows affected (0.38 sec)mysql> INSERT INTO jtable VALUES    ->     ('{"a": 10, "b": "wxyz", "c": "[true, false]"}');Query OK, 1 row affected (0.04 sec)mysql> SELECT * FROM jtable;+----------------------------------------------+| jcol             |+----------------------------------------------+| {"a": 10, "b": "wxyz", "c": "[true, false]"} |+----------------------------------------------+1 row in set (0.00 sec)

现在我们使用JSON_SET()更新列值,这样就可以执行部分更新;在本例中,我们将c键所指向的值(数组[true, false])替换为占用更少空间的值(整数1):

mysql> UPDATE jtable    ->     SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wx", "$.c", 1);Query OK, 1 row affected (0.03 sec)Rows matched: 1  Changed: 1  Warnings: 0mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;+-------------------------+| JSON_STORAGE_FREE(jcol) |+-------------------------+|                      16 |+-------------------------+1 row in set (0.00 sec)

4.2.如何在 binlog 中开启 Partial Updates

这种部分更新可以使用压缩格式写入二进制日志,以节省空间;这可以通过将 binlog_row_value_options选项系统变量设置为PARTIAL_JSON来启用。

binlog_row_value_options 参数是MySQL 8.0.3 版本引入的新参数,该参数主要用于JSON类型的字段更新时,只记录更新的那部分数据到binlog,而不是记录完整的JSON数据,这样能够显著减少JSON字段更新产生的binlog文件大小。

需要注意的是,binlog 中使用 部分更新(Partial Updates),只需满足存储引擎层使用 Partial Updates 的前几个条件,无需考虑变更前后,JSON 文档的空间使用是否会增加。

4.3.关于 Partial Updates 的性能测试

首先构造测试数据,t 表一共有 16 个文档,每个文档近 10 MB。

create table t(id int auto_increment primary key,               json_col json,               name varchar(100) as (json_col->>'$.name'),               age int as (json_col->'$.age'));insert into t(json_col) values(json_object('name', 'Joe', 'age', 24,             'data', repeat('x', 10 * 1000 * 1000))),(json_object('name', 'Sue', 'age', 32,             'data', repeat('y', 10 * 1000 * 1000))),(json_object('name', 'Pete', 'age', 40,             'data', repeat('z', 10 * 1000 * 1000))),(json_object('name', 'Jenny', 'age', 27,             'data', repeat('w', 10 * 1000 * 1000)));insert into t(json_col) select json_col from t;insert into t(json_col) select json_col from t;

接下来,测试下述 SQL:update t set json_col = json_set(json_col, '$.age', age + 1);

在以下四种场景下的执行时间:

在这里插入图片描述
以 MySQL 5.7.36 的查询时间作为基准:

当然,在生产环境,我们一般很少将 binlog_row_image 设置为 MINIMAL。
但即使如此,只开启存储引擎层和 binlog 中的 Partial Updates,查询时间也比 MySQL 5.7 快 4.87 倍,性能提升还是比较明显的。

五、如何对 JSON 字段创建索引

https://blog.csdn.net/weixin_43888891/article/details/130419850

六、mybatis取json类型的数据

https://blog.csdn.net/weixin_43888891/article/details/130438841

七、总结

来源地址:https://blog.csdn.net/weixin_43888891/article/details/130225150

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯