MySQL 利用JSON特性完成复杂数据存储和查询

情景描述

下面一个应用场景,是数据库需要存储文库类的信息。文库分多个种类,比如图书类、论文类等多个类别,每个类别有不同的字段信息。

常规处理方法

要在单张表中去存储不同种类的文库数据,表就会变成这样的结构:

查询语句会是下面这样:

这样的设计会有以下问题:

使用JSON处理

利用JSON解决动态数据问题,MySQL 5.7以后提供了JSON数据类型,可以直接对JSON存储、提取与解析。

因为JSON是弱约束的,因此存储数据非常灵活,同时也可基于虚拟列实现索引优化。

表结构变为如下格式:

 表中插入一些测试数据(对应的SQL脚本在文章底部):

根据表中的dist_request_id字段值进行数据查找,SQL如下:

SELECT * from document WHERE extra->'$.dist_request_id'='5bdba7333cda2ed6f3020cf44c43e2e5';

extra->  指要提取某个字段

$.XXX,$.表示要解析的是JSON数据,XXX是对应JSON中的属性名称。

上面的SQL执行时,将会对整个表进行全表扫描,数据量大时,查询就会慢。

增加虚拟列,解决上述问题,虚拟列是需要跟JSON中的某个属性名称进行对应的。

对JSON中dist_request_id属性创建虚拟列v_request_id,对应的SQL如下:

ALTER TABLE document 
Add COLUMN `v_request_id` varchar(32)  
GENERATED ALWAYS AS (json_unquote(json_extract(`extra`,_utf8mb4'$.dist_request_id'))) VIRTUAL NULL;

SQL解读:

json_extract 代表从指定属性名称中提取对应的属性的值。

json_unquote 去掉JSON中的引号,转为字符串。

VIRTUAL 代表该列为虚拟列。

null 代表字段允许为空。

执行完毕新增虚拟列脚本后,再次查询表数据:

会发现表中多了一列数据,这一列数据就是虚拟列。此时的表结构如下:

虚拟列的数据会自动跟着JSON字符串种关联的属性值变化而变化。

针对虚拟字段进行条件查询,发现仍然是全表扫描,因为还没有建立索引。

现在对虚拟字段建立索引:

create index idx_v_request_id on document(v_request_id);

再次查看执行计划:

此时,索引已经生效了。

通过上面的案例分析,如果要对JSON中其他字段进行查询,同样也可以创建虚拟列,目的就是把JSON中的属性名称映射为一个一个的字段,然后对字段创建索引。

测试数据脚本

使用到的表和数据对应的SQL脚本:


DROP TABLE IF EXISTS `document`;
CREATE TABLE `document`  (`doc_id` int(0) NOT NULL AUTO_INCREMENT,`doc_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`extra` json NULL,PRIMARY KEY (`doc_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of document
-- ----------------------------
INSERT INTO `document` VALUES (1, '十万个为什么', '{\"trade\": [{\"id\": 1, \"name\": \"幼儿\"}, {\"id\": 1, \"name\": \"科普\"}], \"doc_id\": 1, \"doc_name\": \"十万个为什么\", \"properties\": {\"isbn\": \"123456\", \"出版社\": \"文艺出版社\"}, \"doc_type_id\": 1, \"doc_type_name\": \"图书类\", \"dist_request_id\": \"5bdba7333cda2ed6f3020cf44c43e2e5\"}');
INSERT INTO `document` VALUES (2, 'Java从入门到精通', '{\"trade\": [{\"id\": 1, \"name\": \"编程\"}, {\"id\": 1, \"name\": \"IT\"}], \"doc_id\": 1, \"doc_name\": \"Java从入门到精通\", \"properties\": {\"isbn\": \"4556655\", \"出版社\": \"人民邮电出版社\"}, \"doc_type_id\": 1, \"doc_type_name\": \"图书类\", \"dist_request_id\": \"63e0f3dde01d2f0b5c3dda986cf563b6\"}');
INSERT INTO `document` VALUES (3, '论如何成为一个高手', '{\"trade\": [{\"id\": 1, \"name\": \"杂志\"}], \"doc_id\": 1, \"doc_name\": \"论如何成为一个高手\", \"properties\": {\"刊号\": \"20241201\", \"杂志\": \"测试杂志数据BBBB\", \"版面\": \"测试版面数据AAAA\"}, \"doc_type_id\": 2, \"doc_type_name\": \"论文类\", \"dist_request_id\": \"904468b02142dd8d4412254e0fa503f6\"}');

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

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

相关文章

【数据结构】哈希 ---万字详解

unordered系列关联式容器 在C98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log_2 N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好 的查询是&#xff0c…

【Redis篇】Hash的认识以及相关命令操作

目录 前言 基本命令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET HLEN HSETNX HINCRBY HINCRBYFLOAT 内部编码 高内聚,低耦合 前言 可以看出: Redis 的 Hash 是一个键(key)下包含多个字段(field…

可解释机器学习 | Python实现LGBM-SHAP可解释机器学习

机器学习 | Python实现GBDT梯度提升树模型设计 目录 机器学习 | Python实现GBDT梯度提升树模型设计基本介绍模型使用参考资料基本介绍 LightGBM(Light Gradient Boosting Machine)是一种基于决策树的梯度提升框架,是一种高效的机器学习模型。SHAP(SHapley Additive exPlan…

mysql--二进制安装编译安装yum安装

二进制安装 创建用户和组 [rootlocalhost ~]# groupadd -r -g 306 mysql [rootlocalhost ~]# useradd -r -g 306 -u 306 -d /data/mysql mysql 创建文件夹并添加所属文件用户和组 [rootlocalhost ~]# mkdir -p /data/mysql [rootlocalhost ~]# chown mysql:mysql /data/mysql …

大模型开发和微调工具Llama-Factory-->WebUI

WebUI LLaMA-Factory 支持通过 WebUI 零代码微调大模型。 通过如下指令进入 WebUI llamafactory-cli webui# 如果是国内, # USE_MODELSCOPE_HUB 设为 1,表示模型从 ModelScope 魔搭社区下载。 # 避免从 HuggingFace 下载模型导致网速不畅 USE_MODELSC…

【WPS】【EXCEL】将单元格中字符按照分隔符拆分按行填充到其他单元格

问题:实现如下图的效果 解答: 一、函数 IFERROR(TRIM(MID(SUBSTITUTE($A$2,",",REPT(" ",LEN($A$2))),(ROW(A1)-1)*LEN($A$2)1,LEN($A$2))),"") 二、在单元格C2中填写如下函数 三、全选要填充的单元格并且按CTRLD 函数…

Java有关数组的相关问题

Java中的栈和堆的含义 栈 存储局部变量:栈主要用于存储方法中的局部变量,包括基本数据类型(int、double、boolean等)和对象的引用(不包含对象本身)。 遵循后进先出原则:当一个方法被调用时&…

提升阅读体验,Balabolka让文字跃然“声”上

作为一个专业的语音合成工具,Balabolka为用户提供了全方位的文本朗读解决方案。这款软件不仅可以将各类文本实时转换为清晰的语音输出,还能将转换后的音频内容导出为多种主流格式。它强大的兼容性使其能够处理各类电子书和文档格式,让用户可以…

解决`-bash: ./configure:/bin/sh^M:解释器错误: 没有那个文件或目录`的问题

解决`-bash: ./configure:/bin/sh^M:解释器错误: 没有那个文件或目录`的问题 一、错误原因分析二、解决方法方法一:使用`dos2unix`工具方法二:使用`sed`命令方法三:使用`tr`命令方法四:在文本编辑器中转换方法五:在Windows系统中使用适当的工具三、预防措施四、总结在使…

Flink双流Join

在离线 Hive 中,我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢?Flink DataStream API 为我们提供了3个算子来实现双流 join,分别是: join coGroup intervalJoin 下面我们分别详细看一下这…

Python生日祝福烟花

1. 实现效果 2. 素材加载 2个图片和3个音频 shoot_image pygame.image.load(shoot(已去底).jpg) # 加载拼接的发射图像 flower_image pygame.image.load(flower.jpg) # 加载拼接的烟花图 烟花不好去底 # 调整图像的像素为原图的1/2 因为图像相对于界面来说有些大 shoo…

26页PDF | 数据中台能力框架及评估体系解读(限免下载)

一、前言 这份报告详细解读了数据中台的发展历程、核心概念、能力框架及成熟度评估体系。它从阿里巴巴的“大中台,小前台”战略出发,探讨了数据中台如何通过整合企业内部的数据资源和能力,加速业务迭代、降低成本,并推动业务增长…

如何分段存储Redis键值对

说明:本文介绍针对一个value过长的键值对,如何分段存储; 场景 当我们需要存入一个String类型的键值对到Redis中,如下: (缓存接口) public interface CacheService {/*** 添加一个字符串键值…

C-操作符

操作符种类 在C语言中,操作符有以下几种: 算术操作符 移位操作符 位操作符 逻辑操作符 条件操作符 逗号表达式 下标引用,函数调用 拓展:整型提升 我们介绍常用的几个 算术操作符 (加)&#xff…

RabbitMQ 客户端 连接、发送、接收处理消息

RabbitMQ 客户端 连接、发送、接收处理消息 一. RabbitMQ 的机制跟 Tcp、Udp、Http 这种还不太一样 RabbitMQ 服务,不是像其他服务器一样,负责逻辑处理,然后转发给客户端 而是所有客户端想要向 RabbitMQ服务发送消息, 第一步&a…

题海拾贝——生成元(Digit Generator,ACM/ICPC SEOUL 2005,UVa1583)

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 欢迎点赞关注&#xff01; 1、题目描述 如果x加上x的各个数字之和得到y&#xff0c;就说x是y的生成元。给出(1<n<10…

欧科云链研究院:比特币还能“燃”多久?

出品&#xff5c; OKG Research 作者&#xff5c;Hedy Bi 本周二&#xff0c;隔夜“特朗普交易” 的逆转趋势波及到比特币市场。比特币价格一度冲高至约99,000美元后迅速回落至93,000美元以下&#xff0c;最大跌幅超6%。这是由于有关以色列和黎巴嫩有望达成停火协议的传闻引发…

hint: Updates were rejected because the tip of your current branch is behind!

问题 本地仓库往远段仓库推代码时候提示&#xff1a; error: failed to push some refs to 192.168.2.1:java-base/java-cloud.git hint: Updates were rejected because the tip of your current branch is behind! refs/heads/master:refs/heads/master [rejected] (…

设计模式面试大全:说一下单例模式,及其应用场景?

定义 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一&#xff0c;此模式保证某个类在运行期间&#xff0c;只有一个实例对外提供服务&#xff0c;而这个类被称为单例类。 单例模式也比较好理解&#xff0c;比如一个人一生当中只能有一个真…

go-zero使用自定义模板实现统一格式的 body 响应

前提 go环境的配置、goctl的安装、go-zero的基本使用默认都会 需求 go-zero框架中&#xff0c;默认使用goctl命令生成的代码并没有统一响应格式&#xff0c;现在使用自定义模板实现统一响应格式&#xff1a; {"code": 0,"msg": "OK","d…