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

news2024/12/28 8:34:39

目录

    • 一、前言
    • 二、什么是 JSON
    • 三、Mysql当中json函数
    • 四、JSON值部分更新
      • 4.1.使用 Partial Updates 的条件
      • 4.2.如何在 binlog 中开启 Partial Updates
      • 4.3.关于 Partial Updates 的性能测试
    • 五、如何对 JSON 字段创建索引
    • 六、mybatis取json类型的数据
    • 七、总结

一、前言

最近做的一个 填报项目,由于填报的字段比较多于是便在数据库当中使用了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-values

在这里插入图片描述

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。
  • UPDATE语句使用JSON_SET()、JSON_REPLACE()或JSON_REMOVE()这三个函数中的任意一个来更新列。直接赋值列值(例如,UPDATE mytable SET jcol = '{"a": 10, "b": 25}')不能作为部分更新执行。MySQL只能对使用上面列出的三个函数更新值的列执行部分更新。
  • 输入列和目标列必须是同一列,像UPDATE mytable SET jcol1 = JSON_SET(jcol2, '$.a', 100)这样的语句不能作为部分更新执行。
  • 所有的更改都用新的值替换现有的数组或对象值,并且不向父对象或数组添加任何新元素。
  • 被替换的值必须至少与替换值一样大。换句话说,新值不能大于旧值。当先前的部分更新为较大的值留下了足够的空间时,可能会出现此需求的异常。您可以使用JSON_STORAGE FREE()函数查看JSON列的任何部分更新释放了多少空间。
  • JSON文档的部分更新只能在列值上执行。对于存储JSON值的用户变量,该值总是被完全替换,即使使用JSON_SET()执行更新:

JSON_STORAGE_FREE(更新后释放的空间)

  • 描述:主要是记录JSON_SET()、JSON_REPLACE()或JSON_REMOVE()使用这三个函数进行就地更新后,其二进制表示形式释放了多少存储空间。
  • 语法:JSON_STORAGE_FREE(json_val)

返回值:

  • 如果参数是一个JSON列值,并按照前面的描述进行了更新,则返回一个正的非零值,这样它的二进制表示比更新之前占用的空间更少。
  • 假如其二进制表示与以前相同或更大,或者如果更新无法利用部分更新,则返回0
  • 假如没有使用那三个函数,也会返回0

创建测试表

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: 0

mysql> 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
  • MySQL 8.0.27
  • MySQL 8.0.27,binlog_row_value_options=PARTIAL_JSON
  • MySQL 8.0.27,binlog_row_value_options=PARTIAL_JSON + binlog_row_image=MINIMAL

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

  • MySQL 8.0 只开启存储引擎层的 Partial Updates,查询时间比 MySQL 5.7 快 1.94 倍。
  • MySQL 8.0 同时开启存储引擎层和 binlog 中的 Partial Updates,查询时间比 MySQL 5.7 快 4.87 倍。
  • 如果在 2 的基础上,同时将 binlog_row_image 设置为 MINIMAL,查询时间更是比 MySQL 5.7 快 102.22 倍。

当然,在生产环境,我们一般很少将 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

七、总结

  • 使用longtext存储json也可以使用函数等操作,既然mysql出了json数据类型,那我们尽量就使用json数据类型来存储json,而且该数据类型还有数据校验。
  • Mysql提供了大量的json相关函数,基于此,我们针对于一些需求完全可以在sql层面使用函数解决问题,而不需要将数据拿到业务层,然后通过业务代码来解决问题。
  • 尽量使用8.0以上的mysql来使用json数据类型存储json
    • mysql提供了JSON_SET()JSON_REPLACE()JSON_REMOVE()三个函数可以进行值部分更新。其效率是5.7版本的5倍!虽然5.7版本也有这几个函数,但是并不是部分更新!
  • 涉及到根据json当中某个字段查询,我们可以通过虚拟列进行建立索引。同时在MySQL 8.0.17及以后的版本中,InnoDB存储引擎支持JSON数组上的多值索引。
  • 假如使用的是mybatis框架,如果图省事可以直接使用JSONObject来接受前端的值,也可以作为返回值使用,当然也可以自定义json的Java对象,但是都需要设置typeHandler,好处是中间不会出现转义问题,而使用String不需要设置typeHandler,但是会存在转义的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/484798.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[实训] 实验1-SPI数据传输基础实验(上)

目 录​​​​​​​ 一、实验目的 二、实验仪器及器件 三、实验内容及原理 四、实验步骤​​​​​​​ 五、实验测试数据表格记录 六、实验数据分析及处理 七、实验结论与感悟 一、实验目的 使用FPGA/ARM实现SPI数据传输实验;实现数据传输程序的编写、下载…

【项目原理】多点触摸屏驱动原理

一、屏幕介绍 ATK-7016 这款屏幕其实是由 TFT LCD触摸屏组合起来的。底下是 LCD 面板,上面是触摸面板,将两个封装到一起就成了带有触摸屏的 LCD 屏幕。电容触摸屏也是需要一个驱动 IC的,驱动 IC 一般会提供一个 I2C 接口给主控制器&#xff…

[实训] 实验1-SPI数据传输基础实验(下)

目录 五、实验测试数据表格记录 六、实验数据分析及处理 七、实验结论与感悟 五、实验测试数据表格记录 实验现象数码管显示见第四节图4.4,示波器测量结果见下列图片。 图5.1 RST、MOSI/MISO波形测量结果 图5.2 SCLK、MOSI/MISO波形测量结果 仅调整示波器波…

C生万物 | 剖析函数指针经典应用 —— 回调函数

不懂函数指针的老铁可以先看看这篇文章【指针函数与函数指针】,上车,准备出发🚗 文章目录 一、回调函数的概念二、为什么要使用回调函数?三、回调函数使用场景场景一:模拟计算器的加减乘除场景二:模拟qsort…

MySQL集群方案总结与方案原理

前言 在给自己做着玩的一个项目准备数据库集群,顺带自己大致系统复习并记录一下。 单节点mysql存在的常见问题 当数据量和并发量上去后,单节点数据库无法满足大并发时性能上的要求。单节点的MySQL无法满足高可用,数据库宕机或者意外中断等故障…

数据结构学习分享之双向链表详解

数据结构第四课 1.前言2. 结构分析3. 双链表的实现3.1 初始化结构3.2 初始化函数3.3 尾插函数3.4 尾删函数3.5 头插函数3.6 头删函数3.7 销毁链表3.8 其他函数 4. 缓存利用率5. 总结 1.前言 💓博主CSDN:杭电码农-NEO💓🎉🎉&#x…

Python(一) 基础二(语句、文件读写)

1.语句 1.1.if…elif…else 类似于java的if…else if…else语句 1.1.1.判断条件 比较运算符: 、>、<、<、>、!、is、is not、in、not in 1.1.2.和is的区别 list_1 [aaa, bbb] list_2 [aaa, bbb] print(list_1 list_2) #结果:True print(list_1 is list_2)…

async await

async await async await 都是修饰符&#xff0c;修饰函数的。 async/await一定是成对出现的。比如用async也没有什么太大意义。只要函数体中出现了await&#xff0c;则当前函数必须用async来修饰。 用async修饰的函数&#xff0c;相当于用promise包裹起来。其实相当于把同步修…

基于jeecgboot的OA日程安排开发(一)

日程安排也是OA里的一项重要功能&#xff0c;所以基于jeecgboot开发这个日程安排。 日程安排主要涉及以下几个方面&#xff1a; 1、数据库方面&#xff0c;主要是分日历与日程 日历可以分个人日历与工作日历&#xff0c;一般情况下&#xff0c;个人日历只给自己查看&#xff0…

2023-05-02 动态规划简介

动态规划简介 1 动态规划的基本概念 阶段、状态、决策、策略、状态转移方程 1) 阶段和阶段变量 将问题的全过程恰当地分成若干个相互联系的阶段闫氏DP分析法&#xff1a;对应f[i][j]的ij遍历时形成的所有f[i][j]阶段的划分一般根据时间和空间的自然特征去划分阶段的划分便于把…

Nginx原理解析

master和worker 当linux启动的时候&#xff0c;会有两个和nginx相关的进程&#xff0c;一个是master,一个是worker。 master如何工作 当客户端发送请求到nginx之后&#xff0c;master会接收到这个请求&#xff0c;然后通知所有的worker进程&#xff0c;此时&#xff0c;work…

【STL十六】函数对象:包装器(std::function)——绑定器(std::bind)——函数适配器

【STL十六】函数对象&#xff1a;包装器(std::function&#xff09;——绑定器&#xff08;std::bind&#xff09;——函数适配器 一、包装器(std::function&#xff09;1、简介2、头文件3、构造函数4、demo5、异常 二、绑定器&#xff08;std::bind&#xff09;1、简介2、头文…

Nessus漏洞扫描以及OpenSSH漏洞修复验证

主机IP地址资源kali192.168.200.1285GB内存/4CPUCentOS7.5192.168.200.1292GB内存/2CPU https://www.tenable.com/downloads/nessus?loginAttemptedtrue curl --request GET \--url https://www.tenable.com/downloads/api/v2/pages/nessus/files/Nessus-10.5.1-ubuntu1404_am…

云原生Istio案例实战

目录 1 Istio监控功能1.1 prometheus和grafana1.2 访问prometheus1.3 访问grafana 2 项目案例&#xff1a;bookinfo2.1 理解什么是bookinfo2.2 sidecar自动注入到微服务2.3 启动bookinfo2.4 通过ingress方式访问2.5 通过istio的ingressgateway访问2.5.1 确定 Ingress 的 IP 和端…

计算机视觉--图像拼接

图像拼接 单应性变换仿射变换图像扭曲实现图像嵌入&#xff08;图中图&#xff09; RANSAC算法算法介绍图片收集无RANSAC优化和有RANSAC优化的代码实现差别 总结 单应性变换 单应性变换是指一个平面上的点通过一个矩阵变换映射到另一个平面上的点&#xff0c;这个变换矩阵是一…

java聊天室的设计与实现代码

聊天室是一个简单的通信应用&#xff0c;可以帮助您与客户和朋友保持联系&#xff0c;并且可以让您更轻松地与其他员工联系。然而&#xff0c;您将不得不确保每个人都知道他们正在做什么。 一旦聊天室开始&#xff0c;它就会变得非常复杂&#xff0c;因为有许多用户可能会同时登…

【三十天精通Vue 3】第二十五天 Vue3 与 Axios 后端数据交互

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue3 与 Axios 概述二、Axios 安装与基本使用2.1 安装 Ax…

NECCS|全国大学生英语竞赛C类|词汇和语法|语法题|时态|22:30~11:44

15题 10min 10:20&#xff5e;10:25 test2 10:25&#xff5e;10:47 test1订正 10:44&#xff5e;11:47 理论学习 涉及的语法点主要包括&#xff1a; 动词的时态和语态 非谓语动词 虚拟语气 主谓一致 倒装句 强调句 比较级 名词性从句 定语…

【SQL篇】面试篇之子查询

1303 求团队人数 # 写法1 # Write your MySQL query statement below select employee_id, count(*) over(partition by team_id) as team_size from Employee# 写法2 # Write your MySQL query statement below select employee_id, team_size from Employee e join (select t…

优雅编程,从空格、空行、缩进、注释开始

很多初学者的代码其实都不够“漂亮”&#xff0c;那是因为没有养成好的编码习惯。本篇博客以C语言为例&#xff0c;总结一些好习惯。其实&#xff0c;很多习惯都是肌肉记忆&#xff0c;举个例子&#xff1a;请你写一个程序&#xff0c;输入2个整数并输出它们的和。有些朋友可能…