10分钟上手:MySQL8的Json格式字段使用总结干货
一、关于效率和适用范围
尽管官方承诺Json格式字段采用了空间换时间的策略,比Text类型来存储Json有大幅度的效率提升。但是Json格式的处理过程仍然效率不及传统关系表,所以什么时候用Json格式字段尤为重要。
只有我们确定系统已经能精确定位到某一行,比如用主键、创建时间范围等,这时候我们的数据集合比较小,那么我们就可以放心大胆的用Json格式字段进行进一步数据处理,而且Json中所存储的信息一定不是
检索时必要的筛选信息和统计时需要计算的关键数据,不要妄想在百万行Json字段里对某一个Json属性进行搜索、聚合,这属于纯粹找虐。
比如说我们读个字典,以往要拆成两个表,现在一个表就可以解决;或者说ERP系统里我们可以把万年不查的子表、孙表都放在一个Json字段里,这样用单表即可解决复杂结构化数据存储的问题。
举个每个人都知道具体场景的例子:CMS系统有内容页,传统方式解决扩展字段大多都用键值对表(也就是窄表)来解决问题,但事实上键值对表的查询非常慢,所有的数据都以TEXT的方式存储(因为要照顾到富文本自定义字段),因此非常难以查询,当用户已经点击进入内容页的时候我们已知具体是内容表的哪一行,此时直接将JSON数据返回给前端的效率要完全优于
遍历键值对表,而且还能对Json的某个属性加索引,也可以对整个Json串加全文索引,这样对某个栏目下的有限内容的同一个字段就很容易进行统计。
再举一个经常遇到的例子:业务总是在变化,字段总要变,需要兼顾灵活性和效率,不得不用Json字段来处理数据。
二、实测前的准备工作
建表就不用说了,主流建表工具都支持建立Json列。
插入和更新数据也不用说了,就当是操作字符串即可,只有一个局部更新可能需要用到,后面会讲到。
我们这里主要讲查询。
假设我们有这么一个表my_table,后面的例子都用它来举例:
CREATE TABLE `my_table` (`id` bigint NOT NULL AUTO_INCREMENT,`code` varchar(255) NULL,`name` varchar(255) NULL,`attrs` json NULL,`create_time` datetime NULL,`creator` bigint NULL,`last_modify` datetime NULL,`modifier` bigint NULL,`time_stamp` datetime NULL,`deleted` tinyint NULL,PRIMARY KEY (`id`)
);
然后我们准备好要测试的数据
INSERT INTO `my_table` (`id`, `code`, `name`, `attrs`, `create_time`, `creator`, `last_modify`, `modifier`, `time_stamp`, `deleted`)
VALUES (1, 'menu', '菜单', '[{\"code\": \"menu1\", \"name\": \"菜单1\"}, {\"code\": \"menu2\", \"name\": \"菜单2\"}]', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `my_table` (`id`, `code`, `name`, `attrs`, `create_time`, `creator`, `last_modify`, `modifier`, `time_stamp`, `deleted`)
VALUES (2, 'sysConfig', '系统设置', '{\"sysName\": \"某综合管理系统\", \"wxAppId\": \"wx1234567\"}', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `my_table` (`id`, `code`, `name`, `attrs`, `create_time`, `creator`, `last_modify`, `modifier`, `time_stamp`, `deleted`)
VALUES (3, 'site', '站点设定', '[{\"code\": \"a.myweb.com\", \"extra\": {\"owner\": \"rantUser1\"}, \"visited\": 200}, {\"code\": \"b.myweb.com\", \"extra\": {\"owner\": \"rantUser1\"}, \"visited\": 300}, {\"code\": \"www.example.com\", \"extra\": {\"owner\": \"rantUser2\"}, \"visited\": 157}, {\"code\": \"b2c.example.com\", \"extra\": {\"owner\": \"rantUser2\"}, \"visited\": 775}]', NULL, NULL, NULL, NULL, NULL, NULL);
都导入之后,数据大概是这样子的:
各种查询方法
晦涩难懂的官方原版Manual就不给大家重复了,直接上干货:
Json转表
Json转表是第一个要解决的问题,只要变成我们熟悉的表,很多传统MySQL的关联表、集合查询之类的操作都能用上了。
SELECT b.* FROM my_table AS a
JOIN JSON_TABLE( a.attrs, '$[*]' COLUMNS (`code` VARCHAR(20) PATH '$.code',`name` VARCHAR(20) PATH '$.name') ) AS b
WHERE a.code = 'menu'
解析直接看图吧:
查询结果:
取属性
我们很多时候面向对象开发需要用到ORM框架,但每次都要当做String来用FastJson、Gson之类的框架来解析实在是太麻烦。例如我们有MyBatis这样的框架,直接在SQL语句里把Json的字段都附加上,上层所有的应用框架全都可以认,岂不是一劳永逸。
SELECT *,attrs->>'$.sysName' sys_name,attrs->>'$.wxAppId' wx_app_id
from my_table
where code='sysConfig'
查询结果如下:
维度抽取
这个是针对数组的,echarts之类的框架会需要用到,这里不做赘述
select attrs->>'$[*].code' code_list,attrs->>'$[*].name' name_list
from my_table where code='menu'
查询结果:
还可以针对多行一起获得维度抽取的结果,如果碰到JSON不是数组的,它也不会报错,只是返回一个null,非常人性化
select id,code,name,attrs->>'$[*].code' sub_code
from my_table
查询结果:
聚合操作
这次我们把已经设定的站点都取出来,根据所有者的不同,把他们网站的访问量都统计出来
SELECTb.owner,sum(b.visited) visited
FROM my_table AS a
JOIN JSON_TABLE( a.attrs, '$[*]' COLUMNS (`owner` VARCHAR(20) PATH '$.extra.owner',`visited` BIGINT PATH '$.visited') ) AS b
WHEREa.code = 'site'
GROUP BY owner
局部更新
有时候我们并不想把整个Json都更新了,只想更新其中一个值(比如多人同时更新一个Json时,各个内存中完整的Json副本都不一样,如果贸然全量更新,就会互相覆盖)
UPDATE my_table
SET attrs = JSON_SET(attrs, '$.sysName', '某网站管理系统')
WHERE code='sysConfig';
通过上面这个方式就可以局部更新sysName这个key对应的值,MySql内部做了优化,如果值是相同的,影响行数则返回0,它并不会无脑覆盖。
总结
至于其他的用法,对于应用层面开发来说没什么太大用途,主要原因是大批量的Json加工压力还是在前端和后台,所以数据库层面只需要关注读取方式、效率以及和ORM框架的兼容性即可。Json字段对于低代码开发、元数据、动态表单之类的应用是很有帮助的,特别是对有些动态数据结构的加工来说,省了很多精力。
相关文章:

10分钟上手:MySQL8的Json格式字段使用总结干货
一、关于效率和适用范围 尽管官方承诺Json格式字段采用了空间换时间的策略,比Text类型来存储Json有大幅度的效率提升。但是Json格式的处理过程仍然效率不及传统关系表,所以什么时候用Json格式字段尤为重要。 只有我们确定系统已经能精确定位到某一行&am…...

OpenCV 4.9基本绘图
返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV使用通用内部函数对代码进行矢量化 下一篇:使用OpenCV4.9的随机生成器和文本 目标 在本教程中,您将学习如何: 使用 OpenCV 函数 line() 画一…...

显示器and拓展坞PD底层协商
简介: PD显示器或者PD拓展坞方案中,连接显示设备的Type-C端口主要运行在DRP模式,在此模式下可以兼容Source(显卡)、Sink(信号器)、DRP(手机、电脑)模式的显示设备。 Sou…...

如何利用Flutter将应用成功上架至iOS平台:详细指南
引言 🚀 Flutter作为一种跨平台的移动应用程序开发框架,为开发者提供了便利,使他们能够通过单一的代码库构建出高性能、高保真度的应用程序,同时支持Android和iOS两个平台。然而,完成Flutter应用程序的开发只是第一步…...

【运输层】网络数据报协议 UDP
目录 1、UDP 的特点 2、UDP 的首部格式 UDP 只在 IP 协议之上增加了很少的一些功能,比如复用、分用以及差错检测等。 1、UDP 的特点 UDP是无连接的,即发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。 UDP使用尽最大努力…...
数据结构(初阶):顺序表实战通讯录
前言 数据结构(初阶)第一节:数据结构概论-CSDN博客 数据结构(初阶)第二节:顺序表-CSDN博客 本文将以C语言和顺序表实现通讯录基础管理,实现功能包括增、删、改、查等,在实现相关功能…...

Outlook会议邀请邮件在答复后就不见了
时常会有同事找到我说,Outlook答复会议邀请邮件后收件箱就找不到会议邀请的邮件了。 这其实是Outlook的的一个机制,会把应答后的会议邀请邮件从收件箱自动删除,到已删除的邮件那里就能找到。如果不想要自动删除,改一个设置即可。…...

【C++】list模拟实现
个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. list源码3. 初始化3.1 构造3.2 拷贝构造3.3 赋值3.4 析构 4. 迭代器4.1 后置加加和前置加加4.2 后置减减和前置减减4.3 解引用4.4 !和4.5 begin 和 end4.6 const迭代器4.7 迭代器优化 5. Modifi…...

ETL工具-nifi干货系列 第八讲 处理器PutDatabaseRecord 写数据库(详细)
1、本节通过一个小例子来讲解下处理器PutDatabaseRecord,该处理器的作用是将数据写入数据库。 如下流程通过处理器GenerateFlowFile 生成数据,然后通过处理器JoltTransformJSON转换结构,最后通过处理器PutDatabaseRecord将数据写入数据库。如…...

【MySQL】如何判断一个数据库是否出问题
在实际的应用中,其实大多数是主从结构。而采用主备,一般都需要一定的费用。 对于主备,如果主机故障,那么只需要直接将流量打到备机就可以,但是对于一主多从,还需要将从库连接到主库上。 对于切换的操作&a…...
SQLite数据库的性能问题并不是单纯地由数据量的大小决定的,而是受到多种因素的综合影响。以下是一些可能导致SQLite性能问题的因素
SQLite数据库的性能问题并不是单纯地由数据量的大小决定的,而是受到多种因素的综合影响。以下是一些可能导致SQLite性能问题的因素: 数据量:当SQLite数据库中的数据量增长到一定程度时,查询、插入和更新等操作可能会变得缓慢。这…...

Blender怎么样启动默认移动和Cavity效果
在使用Blender的过程中,有一些特殊的技巧很重要。 比如默认地设置blender打开时,就是移动物体,这样怎么样设置的呢? 需要在界面里打开下面的菜单: 这样就找到默认设置的地方,把下面的移动勾选起来,这样点…...
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
关键计算地方: 1.当前是上滑动还是下滑动(相对于屏幕) ,使用ev.getRawY()获得当前滑动位置在屏幕哪个地方 2. 计算文本客滑动到哪里即可停止, (行高*总文本行数)- (行高 * 最多显示行数) int sum getLineHeight() * getLineCount() - getLineHeight() * getMaxLines(); …...
Laravel 开发Api规范
一,修改时区 配置 config/app.php 文件 // 时区修改,感觉两者皆可,自己根据实际情况定义 timezone > PRC, // 大陆时间二,设置 Accept 头中间件 accept头即为客户端请求头,做成中间件来使用。Accept 决定了响应返…...

蓝色wordpress外贸建站模板
蓝色wordpress外贸建站模板 https://www.mymoban.com/wordpress/7.html...

windos环境,使用docker容器运行项目的,新增外部访问地址配置
对于运行在 Docker 容器中的项目,你需要在容器内部编辑 resolv.conf 文件。以下是一种常见的方法: 进入正在运行的 Docker 容器:docker exec -it [container_id] bash其中 [container_id] 是你正在运行的 Docker 容器的 ID。 在容器内部使…...
设计模式:生活中的组合模式
想象一下,你正在组织一个大型的家庭聚会。在这个聚会中,你需要准备各种菜肴,每个菜肴又包含不同的食材。你的目标是能够以统一的方式处理整个聚会的准备工作,不论是处理单个食材还是一整道菜肴。 在这个场景中,我们可…...
WPF OnStartup
在Windows Presentation Foundation (WPF)框架中,OnStartup 是 System.Windows.Application 类的一个受保护的虚方法,它是应用程序启动过程中的一个重要环节。当一个 WPF 应用程序启动时,其入口点通常是 App.xaml 文件和对应的后台代码文件 A…...
docker-相关
打镜像 1、编写dockfile文件,请自行百度 2、docker build -t 镜像名称:版本号 dockerFile路径 3、docker save -o 镜像压缩包名称.tar 镜像名称:镜像版本号 部署镜像 1、将镜像tar包放到部署机器上 2、加载镜像:docker load -i 镜像tar包路径 3、dock…...
二十、Rust AOP 切面增强
用过 java spring 的同学,应该会对 AspectJ 的 前置、后置、环绕 增强 念念不忘,巧了 rust 也有类似能力,稍显不同的是,为了向 “零成本抽象” 靠齐,Rust 的 “增强” 是在编译期 完成的。 编译期生成,则离…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...