mysql 5.7中有很多新的特性,但平时可能很少用到,这里列举2个实用的功能:虚拟列及json字段类型

一、先创建一个测试表:

1

2

3

4

5

6

7

8

9

drop table  if exists t_people;

CREATE TABLE t_people(

  `id` INT(11) NOT NULL AUTO_INCREMENT,

  `namevarchar(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 

二、生成测试数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

delimiter //

-- 写一段存储过程,方便后面生成测试数据

create procedure batchInsert()

 begin

  declare 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个字做索引

1

alter table t_people add key ix_name(name(1));

确实是个好办法,效果也不错

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

依然会全表扫描。

四、虚拟列

1

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时也无法指定字段值。

然后在这个列上创建索引:

1

alter table t_people add index ix_second_name(`second_name`);

再来看下执行计划,索引生效了,扫描行数也明显下降。

当然,sql语句也可以改成:

1

explain select count(0) from t_people where second_name='杨';

这样看上去更直观,效果不变。

五、json检索

又来新需求了:要查profile中手机号为13589135467,并且姓“吴”的人

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

分析执行计划,可以看到前缀索引“ix_name”生效了,但还有优化空间,仍然可以借助虚拟列,创建2个虚拟列phone、first_name,并创建联合索引。

1

2

3

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:

1

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修改虚拟列属性失败_mysql虚拟列(Generated Columns)及JSON字段类型的使用

    mysql 5.7中有很多新的特性,但平时可能很少用到,这里列举2个实用的功能:虚拟列及json字段类型 一.先创建一个测试表: drop table if exists t_people; CREA ...

  2. mysql 虚拟列索引_使用MySQL 5.7虚拟列提高查询效率

    原标题:使用MySQL 5.7虚拟列提高查询效率 导读 翻译团队:星耀队@知数堂 团队成员:星耀队-芬达,星耀队-顺子,星耀队-M哥 原文出处:https://www.percona.com/blog ...

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

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

  4. PostgreSQL 生成列(Generated Columns)教程

    PostgreSQL 12 增加新的特性--生成列(Generated Columns),也就是计算列.在之前版本也可以实现,但需要定义函数和触发器,利用该功能可以更容易使用并可以提升性能. 生成列是 ...

  5. thinkphp mysql json数据类型_ThinkPHP:JSON字段类型的使用(ORM)

    ThinkPHP5.1版本正式发布已经有一段时间了,我会陆续给大家介绍其中的新特性.今天要给大家介绍的是一个可能很多用户还不了解的一个特性:JSON字段数据支持.不过首先注意一点,本篇内容中描述的JS ...

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

    mysql5.7支持的json字段查询 使用示例: 存储结构如下: 1.以json字段作为查询条件:[json字段全部是JSONObject类型的] SELECT * FROMworksheet_da ...

  7. thinkphp josn mysql_ThinkPHP:JSON字段类型的使用(ORM)

    ThinkPHP5.1版本正式发布已经有一段时间了,我会陆续给大家介绍其中的新特性.今天要给大家介绍的是一个可能很多用户还不了解的一个特性:JSON字段数据支持.不过首先注意一点,本篇内容中描述的JS ...

  8. MySQl中文1001无标题_Mysql中字段类型不一致导致索引无效的处理办法

    前两天有个同事算数据,写出来的sql执行很慢.那个sql也很简单,就是一个左联带条件的查询.explain之后发现,其中有一张表没有用到索引.初始以为是没有建索引,于是建上索引再试,发现问题依旧.后来 ...

  9. mysql enum和set_mysql enum和set字段类型的使用

    CREATE TABLE test_enum( id TINYINT, e enum('FISH','APPLE','DOG','HAMBURG') NOT NULL ); INSERT INTO t ...

最新文章

  1. 湫湫系列故事——消灭兔子
  2. 路由器中虚拟服务器设置,路由器中虚拟服务器设置方法
  3. 三维重建:深度传感技术的中外差异
  4. 网站搭建从零开始(五) WordPress的安装
  5. Windows 任务栏缩略图自定义程序[更新 Build20100830]
  6. leetcode算法—两数相加 Add Two Numbers
  7. matlab 带通滤波函数,用matlab制作带通滤波器.doc
  8. 阿里语音识别(语音转文字)java调用全程手把手详解-适合中小学生快速上手
  9. 汇编指令-bic(位清除)、orr(位或)(3)
  10. 关闭键盘按键声音和使用筛选键
  11. html 在线测试 鱼缸,新做的草缸教程,看1遍你也会做,鱼缸造景其实很简单
  12. 2020阿里巴巴社招面试题
  13. 督办管理系统项目总结
  14. 快牛策略——PowerPoint 2003:红头文件的制作及标准
  15. 2021东软始业教育考试
  16. 热烈祝贺我公司获得“渣土车智慧监控平台软件著作权登记证书”
  17. 使用预装Win10的戴尔电脑最新恢复出厂设置方法
  18. 批处理find 命令使用
  19. 今天全网的网站都变成了灰色了,这其中是如何实现的呢?
  20. iphone 越狱后

热门文章

  1. 寒冷的高纬度——我的梦开始的地方
  2. PTA第3章-2 查验身份证 (15 分)
  3. VIM-配置-.vimrc
  4. 对现有的所能找到的DDOS代码(攻击模块)做出一次分析----其他(攻击方式)篇
  5. RabbitMQ之镜像队列
  6. [九]RabbitMQ-客户端源码之Consumer
  7. 设计模式:享元模式(Flyweight)
  8. LiveVideoStack Meet | 苏州站全记录
  9. 京东智联云分布式低延时RTC系统
  10. 深度学习在AEC中的应用探索