mysql json 虚拟列_JSON & 虚拟列

本文介绍了MySQL 5.7中的虚拟列(Virtual Generated Column),默认不持久化,常用于减少冗余数据。通过示例展示了如何配合JSON数据类型,创建虚拟列v_age自动提取JSON对象中的age字段,并讨论了虚拟列的索引和更新行为。建议在团队开发中使用前缀v_来标记虚拟列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是虚拟列?

在MySQL 5.7中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column,前者只将Generated Column保存在数据字典中(表的元数据),并不会将这一列数据持久化到磁盘上;后者会将Generated Column持久化到磁盘上,而不是每次读取的时候计算所得。很明显,后者存放了可以通过已有数据计算而得的数据,需要更多的磁盘空间,与Virtual Column相比并没有优势,因此,MySQL 5.7中,不指定Generated Column的类型,默认是Virtual Column。

如果需要Stored Generated Golumn的话,可以在Virtual Generated Column上建立索引更加合适

综上,一般情况下,都使用Virtual Generated Column,这也是MySQL默认的方式

特殊用途冗余列

列长度还是和定义类型一样

能正常加索引

查询效率上,物理>STORED>VIRTUAL

应用

这里配合5.7开始支持的json,来体验一下虚拟列的使用

1. 创建表

CREATE TABLE user_info (

uid INT(11) NOT NULL AUTO_INCREMENT,

uname VARCHAR(20) NOT NULL DEFAULT '',

other_info json,

PRIMARY KEY(uid)

) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;

2. 写入数据

## 两种写入json数据方式

INSERT INTO user_info (uname,other_info) VALUES ('first user',JSON_OBJECT("age",22,"real_name","Wayne","sex","男"));

INSERT INTO user_info (uname,other_info) VALUES ('second user','{"age":21, "real_name":"Jone", "sex":"女", "height":170, "weight":48}');

数据如图:

c77785c79736f3515f0bae07c6725585.png

mysql> select * from user_info where other_info->'$.age'='24';

+-----+------------+---------------------------------------------------+-------+

| uid | uname      | other_info                                        | v_age |

+-----+------------+---------------------------------------------------+-------+

|   1 | first user | {"age": "24", "sex": "男", "real_name": "Wayne"}  |    24 |

+-----+------------+---------------------------------------------------+-------+

1 row in set (0.00 sec)

mysql> select * from user_info where json_extract(other_info,'$.age')='24';

+-----+------------+---------------------------------------------------+-------+

| uid | uname      | other_info                                        | v_age |

+-----+------------+---------------------------------------------------+-------+

|   1 | first user | {"age": "24", "sex": "男", "real_name": "Wayne"}  |    24 |

+-----+------------+---------------------------------------------------+-------+

1 row in set (0.00 sec)

3.增加虚拟列 v_age(养成加前缀的好习惯, 例如这里使用"v_"来标记该字段是一个虚拟字段,在团队开发时,共同遵守一个约定, 相互配合起来会非常顺利)

##默认是Virtual Column,虚拟列不持久化

ALTER TABLE user_info ADD COLUMN v_age TINYINT(3) UNSIGNED GENERATED ALWAYS AS (other_info->'$.age');

更新以后的表结构如下:

ff8c7c999da8b8b9789cc56957a24b45.png

4. 查看更新后的数据

可以看到v_age已自动提取了other_info中的age字段

6ee1b17b05716128dedcbd126fe2ccb1.png

更新一下记录,把id=1的age更新为24

UPDATE user_info SET other_info=json_set(other_info,'$.age','24') WHERE uid=1;

再来看下数据,对应的v_age也更新为24,是不是有点像视图的感觉,哈哈

fc09c7bfbc7024b1e6c4340816f5e006.png

这里注意一下,insert时不要给虚拟列设定值, 否则会报错(这里就体现出了加前缀的好处,不管是别人还是自己,看到v_前缀就会意识到这是一个虚拟列,就不至于写出类似的错误语句了)

855a7930acc643ed277007987c47ff1a.png

5. 关于索引,json字段无法对其中一个值使用索引,而虚拟列是支持索引的, 可以利用这一特性来索引json字段的某个值

#创建索引

ALTER TABLE user_info ADD INDEX v_age(v_age);

使用explain来查看一下v_age索引的使用情况,可以看到使用的索引的为v_age

4d3a043c15542c1e7efdff131766cc60.png

https://www.cnblogs.com/nkefww/p/9964874.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值