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)
随机推荐
- 支持国产,为deepin添把柴,全面切换到deepin;
虽然不是技术型,但是对deepin的支持必须有的. 只希望国产系统越来越好.国产软件越来越好. 软件生态也越来越好! 等搞完高精密仪器问题,cpu自己造了,下来估计就要整顿软件行业. 我这里要时刻准备 ...
- 通过adb访问SQLite数据库
根据<第一行代码>第二版进入到数据库的文件夹,但是如果照书本直接cd data/data/包名/databases 的话是会报错的,错误信息如下 cd: /data/data/包名 /da ...
- 一个包含 80+ C#/.NET 编程技巧实战练习开源项目!
项目介绍 C#/.NET/.NET Core编程常用语法.算法.技巧.中间件.类库.工作业务实操练习集,配套详细的文章教程讲解,助你快速掌握C#/.NET/.NET Core中各种编程常用语法.算法. ...
- 【笔记】用伽马函数证明标准正态分布EX4的值为3
2020-11-13 看了博客标准正态分布的E(X^4)积分求解的极坐标变换证明方法,已经叹服不已,然后看了底下老哥的评论,用伽马函数可以口算出来,遂去查了一下,真香!发篇博客记录一下. 现在的问题, ...
- eclipse左边窗口再次出现的方法
1.WindowsShow ViewOtherProject Explorer 2.WindowsShow ViewProject Explorer
- 推荐一个kafka可视化客户端GUI工具(Kafka King)
Kafka King,比较新,只需要填写kafka连接地址就行,不需要什么zookeeper. 支持的功能也多: 查看集群节点列表(完成) 创建主题(支持批量).删除主题.支持根据消费者组统计每个to ...
- React-Native开发鸿蒙NEXT-cookie设置
React-Native开发鸿蒙NEXT-cookie设置 应用有个积分商城,做一些积分兑换的业务,就一个基于react-native-webview开发的页面,在页面加载的时候通过js注入来设置co ...
- 基于 Streamlit 和 OpenAI 实现的小红书爆款文案生成器
项目介绍 在当今自媒体时代,高质量的文案是吸引流量的关键.特别是在小红书这样的平台上,一个吸引人的标题和富有情感的正文可以显著提高内容的曝光率. 本文将介绍一个基于OpenAI API和Streaml ...
- Springboot笔记<7>过滤器与拦截器
过滤器 拦截器 过滤器 过滤器拦截的是URL Spring中自定义过滤器(Filter)一般只有一个方法,返回值是void,当请求到达web容器时,会探测当前请求地址是否配置有过滤器,有则调用该过滤器 ...
- Springboot笔记<6>Rest的使用和请求参数注解@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody
Rest的使用和原理 Rest风格支持(使用HTTP请求方式动词来表示对资源的操作) • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveU ...