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字段类型的使用的更多相关文章

  1. mysql 虚拟列导入报错1906说明

    当表中有虚拟列,使用mysqldump导出后,执行source导入的时候,会出现下列错误: 对于mariadb 10.2,该错误忽略即可,不影响导入.对于mysql 5.7,截止5.7.9该错误没有解 ...

  2. mysql中,通过json_insert函数向json字段插入键值?json_insert函数的使用?

    需求描述: 通过json_insert向json字段中插入值,在此进行实验,记录下. 操作过程: 1.查看已经有的包含json数据类型的表 mysql> select * from tab_js ...

  3. mysql 5.7 json 字段类型查找、修改

    修改 json 里的数组字段 mysql> set @json = '{"test": [{"name": "laravel"}, { ...

  4. 【mysql】mysql5.7支持的json字段查询【mybatis】

    mysql5.7支持的json字段查询 参考:https://www.cnblogs.com/ooo0/p/9309277.html 参考:https://www.cnblogs.com/pfdltu ...

  5. 数据库json字段类型总结

    ----------------------------------------=================以下是个人自己总结,可能只有自己看的懂.===================---- ...

  6. MySQL查询列必须和group by字段一致吗?

    @ 目录 场景:查询各部门薪水最高的员工. 方法一: 方法二: MySQL group by是如何决定哪一条数据留下的? 分组前的数据: 那么target list和group by column不匹 ...

  7. MYSQL实现列拼接,即同一个字段,多条记录拼接成一条

    一.首先,新建三张表 DROP TABLE IF EXISTS `article`; CREATE TABLE `article` ( `id` ) unsigned NOT NULL AUTO_IN ...

  8. mysql 虚拟列

    http://blog.csdn.net/yueliangdao0608/article/category/351407

  9. mysql5.7 新增的json字段类型

    一.我们先创建一个表,准备点数据 CREATE TABLE `json_test` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'I ...

  10. mysql 表中已经存在数据 修改字段类型 varchar(11) 改为 int(11)

    update tablename set s_role = '' alter table  tablename  modify column s_role int(11)

随机推荐

  1. 支持国产,为deepin添把柴,全面切换到deepin;

    虽然不是技术型,但是对deepin的支持必须有的. 只希望国产系统越来越好.国产软件越来越好. 软件生态也越来越好! 等搞完高精密仪器问题,cpu自己造了,下来估计就要整顿软件行业. 我这里要时刻准备 ...

  2. 通过adb访问SQLite数据库

    根据<第一行代码>第二版进入到数据库的文件夹,但是如果照书本直接cd data/data/包名/databases 的话是会报错的,错误信息如下 cd: /data/data/包名 /da ...

  3. 一个包含 80+ C#/.NET 编程技巧实战练习开源项目!

    项目介绍 C#/.NET/.NET Core编程常用语法.算法.技巧.中间件.类库.工作业务实操练习集,配套详细的文章教程讲解,助你快速掌握C#/.NET/.NET Core中各种编程常用语法.算法. ...

  4. 【笔记】用伽马函数证明标准正态分布EX4的值为3

    2020-11-13 看了博客标准正态分布的E(X^4)积分求解的极坐标变换证明方法,已经叹服不已,然后看了底下老哥的评论,用伽马函数可以口算出来,遂去查了一下,真香!发篇博客记录一下. 现在的问题, ...

  5. eclipse左边窗口再次出现的方法

    1.WindowsShow ViewOtherProject Explorer 2.WindowsShow ViewProject Explorer

  6. 推荐一个kafka可视化客户端GUI工具(Kafka King)

    Kafka King,比较新,只需要填写kafka连接地址就行,不需要什么zookeeper. 支持的功能也多: 查看集群节点列表(完成) 创建主题(支持批量).删除主题.支持根据消费者组统计每个to ...

  7. React-Native开发鸿蒙NEXT-cookie设置

    React-Native开发鸿蒙NEXT-cookie设置 应用有个积分商城,做一些积分兑换的业务,就一个基于react-native-webview开发的页面,在页面加载的时候通过js注入来设置co ...

  8. 基于 Streamlit 和 OpenAI 实现的小红书爆款文案生成器

    项目介绍 在当今自媒体时代,高质量的文案是吸引流量的关键.特别是在小红书这样的平台上,一个吸引人的标题和富有情感的正文可以显著提高内容的曝光率. 本文将介绍一个基于OpenAI API和Streaml ...

  9. Springboot笔记<7>过滤器与拦截器

    过滤器 拦截器 过滤器 过滤器拦截的是URL Spring中自定义过滤器(Filter)一般只有一个方法,返回值是void,当请求到达web容器时,会探测当前请求地址是否配置有过滤器,有则调用该过滤器 ...

  10. Springboot笔记<6>Rest的使用和请求参数注解@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

    Rest的使用和原理 Rest风格支持(使用HTTP请求方式动词来表示对资源的操作) • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveU ...