mysql虚拟列(Generated Columns)及JSON字段类型的使用
mysql 5.7中有很多新的特性,但平时可能很少用到,这里列举2个实用的功能:虚拟列及json字段类型
一、先创建一个测试表:
drop table if exists t_people; CREATE TABLE t_people(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '',
`profile` json not null ,
`created_at` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
`updated_at` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id));
注:这里profile是一个json类型的字段,另db编码采用utf8mb4
二、生成测试数据
delimiter // -- 写一段存储过程,方便后面生成测试数据
create procedure batchInsert()
begin
declare i int;
declare v_name varchar(50);
declare v_profile varchar(100);
set i=0;
while i<100000 do
set v_name = concat(substring('赵钱孙李周吴郑王张杨',floor(1+(rand()*10)),1),substring('菩提树下的杨过',floor(1+(rand()*7)),1),substring('我爱北京天安门',floor(1+(rand()*7)),1),i);
set v_profile = concat("{\"phone\":\"",concat('13',floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9)),floor(1+(rand()*9))) , "\",\"age\":",i,"}");
insert into t_people(`name`,profile) values(v_name,v_profile);
set i=i+1;
end while;
end; //
注:这段存储过程不是本文重点,看不懂的同学不用深研,大概意思就是name随机生成,profile随机生成一个类似{"phone":"13xxxxxx","age":x}的内容。
调用一下这个存储过程,生成100000条测试数据,数据大致长下面这样:

需求来了,假如我们要查姓“张”的人有多少个?

这显然是一个全表扫描!
三、前缀索引
肯定有同学想到了,在name上建一个前缀索引,只对name的第1个字做索引
alter table t_people add key ix_name(name(1));
确实是个好办法,效果也不错

但是需求总是变化的,如果想查第2个字是“杨”的人有多少?

依然会全表扫描。
四、虚拟列
alter table t_people add second_name varchar(3) generated always as(substring(name,2,1)) stored;
创建了一个虚拟列second_name,其值是substring(name,2,1),即name中的第2个字,最后的stored表示,数据写入时这个列的值就会计算(详情可参考最后的参考链接)
注:虚拟列并不是真正的列,insert时也无法指定字段值。
然后在这个列上创建索引:
alter table t_people add index ix_second_name(`second_name`);
再来看下执行计划,索引生效了,扫描行数也明显下降。

当然,sql语句也可以改成:
explain select count(0) from t_people where second_name='杨';
这样看上去更直观,效果不变。
五、json检索
又来新需求了:要查profile中手机号为13589135467,并且姓“吴”的人

注意:profile->"$.phone"=xxx 就是json字段的检索语法

分析执行计划,可以看到前缀索引“ix_name”生效了,但还有优化空间,仍然可以借助虚拟列,创建2个虚拟列phone、first_name,并创建联合索引。
alter table t_people add first_name varchar(3) generated always as(substring(name,1,1)) stored;
alter table t_people add phone varchar(20) generated always as(profile->"$.phone") stored;
alter table t_people add index ix_phone_firstname(phone,first_name);
加了这2个虚拟列后,数据长这样:

注:phone列提取出来后,前后会带上引号。
刚才的需求,可以改写sql:
select * from t_people where phone='\"13589135467\"' and name like '吴%';
最后看下执行计划:

扫描行数下降到个位数,效果十分明显。
参考文章:
http://mysqlserverteam.com/generated-columns-in-mysql-5-7-5/
https://dev.mysql.com/doc/refman/5.7/en/json.html
mysql虚拟列(Generated Columns)及JSON字段类型的使用的更多相关文章
- mysql 虚拟列导入报错1906说明
当表中有虚拟列,使用mysqldump导出后,执行source导入的时候,会出现下列错误: 对于mariadb 10.2,该错误忽略即可,不影响导入.对于mysql 5.7,截止5.7.9该错误没有解 ...
- mysql中,通过json_insert函数向json字段插入键值?json_insert函数的使用?
需求描述: 通过json_insert向json字段中插入值,在此进行实验,记录下. 操作过程: 1.查看已经有的包含json数据类型的表 mysql> select * from tab_js ...
- mysql 5.7 json 字段类型查找、修改
修改 json 里的数组字段 mysql> set @json = '{"test": [{"name": "laravel"}, { ...
- 【mysql】mysql5.7支持的json字段查询【mybatis】
mysql5.7支持的json字段查询 参考:https://www.cnblogs.com/ooo0/p/9309277.html 参考:https://www.cnblogs.com/pfdltu ...
- 数据库json字段类型总结
----------------------------------------=================以下是个人自己总结,可能只有自己看的懂.===================---- ...
- MySQL查询列必须和group by字段一致吗?
@ 目录 场景:查询各部门薪水最高的员工. 方法一: 方法二: MySQL group by是如何决定哪一条数据留下的? 分组前的数据: 那么target list和group by column不匹 ...
- MYSQL实现列拼接,即同一个字段,多条记录拼接成一条
一.首先,新建三张表 DROP TABLE IF EXISTS `article`; CREATE TABLE `article` ( `id` ) unsigned NOT NULL AUTO_IN ...
- mysql 虚拟列
http://blog.csdn.net/yueliangdao0608/article/category/351407
- mysql5.7 新增的json字段类型
一.我们先创建一个表,准备点数据 CREATE TABLE `json_test` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'I ...
- mysql 表中已经存在数据 修改字段类型 varchar(11) 改为 int(11)
update tablename set s_role = '' alter table tablename modify column s_role int(11)
随机推荐
- 当数据爆炸遇上SQL Server:优化策略全链路解析
在数据驱动的时代,海量数据冲击下的数据库性能成为系统成败的关键.SQL Server作为企业级数据库的常青树,面对单表亿级数据量时,我们往往陷入分库分表与否的抉择困境. 我们站在SQL Server视 ...
- 看完这章你也会黑盒edu通杀
负责声明: 请勿利用文章内的相关技术从事非法测试,由于传播.利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关.该文章仅供学习用途 ...
- 数据库事务回滚:FastAPI中的存档与读档大法
title: 数据库事务回滚:FastAPI中的存档与读档大法 date: 2025/05/10 00:18:52 updated: 2025/05/10 00:18:52 author: cmdra ...
- SQL 强化练习 (六)
本以为学会了Python 就已经天下无敌, 果然, 我还是太傻太天真了. 业务中几乎就没有用 Python 来直接连接数据库进行操作, 当然我是说数据这块哈. 哎, 难受, 还是用的 sql 这种方式 ...
- BP算法完整推导 2.0 (下)
上篇主要阐述 BP算法的过程, 以及 推导的 4 大公式的结论, 现在呢要来逐步推导出这写公式的原理. 当理解到这一步, 就算真正理解 BP算法了. 也是先做一个简单的回顾一下, 不是很细, 重点在推 ...
- AI法律助手:打造普惠法律服务的未来
当法律服务遇见人工智能,普通人的维权之路将不再艰难 当法律服务成为奢侈品,AI或许是唯一出路 2025年的一个深夜,我刷着手机,一条新闻让我停下了滑动的手指: "某平台家装工人因合同纠纷讨薪 ...
- Friend Circles(dfs)——LeetCode进阶路
原题链接https://leetcode.com/problems/friend-circles/ 题目描述 There are N students in a class. Some of them ...
- Web前端入门第 57 问:JavaScript 数据类型与类型转换
在程序语言中,数据类型是基础,一切程序都是建立在基础数据之上. 如果说程序如同万丈高楼平地起,那么数据类型就像沙.石.钢筋.水泥等等最基础的原料.一样的高楼,不同的人,用相同的原料,造的方法也会有千般 ...
- Hitachi Vantara Programming Contest 2024(AtCoder Beginner Contest 368)题解A~D
A - Cut 题意: 将数组的后k个字符移到前面 思路: 可以用rotate()函数让数组中的元素滚动旋转 rotate(v.begin(), v.begin() + n - k, v.end()) ...
- XXL-MQ v1.4.0 | 轻量级分布式消息队列
Release Notes 1.[重构]XXL-MQ 核心代码重构,基于"存算分离"与"分区机制"设计思想.在轻量级.分布式的基础上,强化高吞吐.海量消息及水平 ...