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…

单例模式的理解和实践

在软件开发中,设计模式是开发者在特定情境下,对常见问题的通用解决方案。这些模式帮助开发者以更高效、可维护的方式编写代码。其中,单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个…

zerotier实现内网穿透

zerotier的内网穿透 前言一、zerotier的框架认知二、客户端安装设置1.linux2.windows 前言 摸索了一阵,看了好几篇,没有讲清楚。争取这次说清楚。 一、zerotier的框架认知 先认识一下zerotier的框架,这样如何处理就很好理解了。 首先上zero…

windows11 使用体验记录

好的地方: UI上字体风格貌似更好看了,文件夹增加了多个标签,类似于浏览器既可以打开多个窗口,也可以在同一个窗口中打开多个标签页 不好的地方: 桌面右下角点击日期时间,显示日期,时间呢&…

牛客周赛 Round 70 A-E

本期封面原图 画师村カルキ 牛客周赛 Round 70 五题 A - 小苯晨跑 思路 没啥好说的 代码 // // Created by Swan416 on 2024-12-01 18:57. // #include <bits/stdc.h> #define maxOf(a) *max_element(a.begin(),a.end()) #define minOf(a) *min_element(a.begin(),a.…

C++20: 像Python一样split字符串

概要 Python 的字符串天生支持 split( ) 操作&#xff0c;支持单个字符或字符串作为分隔符。 C 在这方面显得很笨拙&#xff0c;但是在 C20 下经过一番尝试&#xff0c;还是能够提供类似的简洁调用。 Python 代码 s 0,11,336,23,370nums s.split(,) for n in nums:print(n…

oracle数据库日常操作

1、执行SQL语句后不显示PL/SQL procedure successfully completed set feedback off; 2、显示实例名称 echo "set sqlprompt \"_user_connect_identifier> \"" >> $ORACLE_HOME/sqlplus/admin/glogin.sql 3、客户端尝试连接到服务器时发生超时 …

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

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

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

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

<回文判断>

【问题描述】 回文是正读和倒读都一样的句子。读入一个最大长度不超过50个字符的句子&#xff0c;判断其是否是回文。 【输入形式】 输入一个最大长度不超过50个字符的句子 【输出形式】 Yes/No 【输入样例】 abcba 【输出样例】 Yes 【样例说明】 输入abcba&#xff0c;判…

VPP多架构处理器支持

对于转发层面的关键节点&#xff08;node&#xff09;&#xff0c;VPP针对处理器架构编译多份代码&#xff0c;在运行时检测处理器架构&#xff0c;动态确定使用的代码分支。VPP提供两种对多处理器架构的支持&#xff0c;除了节点函数外&#xff0c;还可指定任意函数支持多架构…

算法2--滑动窗口

滑动窗口 滑动窗口经典例题长度最小的子数组无重复字符的最长子串[最大连续1的个数 III](https://leetcode.cn/problems/max-consecutive-ones-iii/description/)[将 x 减到 0 的最小操作数](https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/description…

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# 如果是国内&#xff0c; # USE_MODELSCOPE_HUB 设为 1&#xff0c;表示模型从 ModelScope 魔搭社区下载。 # 避免从 HuggingFace 下载模型导致网速不畅 USE_MODELSC…

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

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

Java有关数组的相关问题

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

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

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

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

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

第一部分:基础知识 1. 介绍 --[MySQL轻松入门教程]

什么是MySQL&#xff1f; MySQL 是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它使用结构化查询语言&#xff08;SQL&#xff09;来管理数据。MySQL 由瑞典公司 MySQL AB 开发&#xff0c;现在归 Oracle Corporation 所有。MySQL 是开源软件…

Flink双流Join

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