mysql中生成列与JSON类型的索引

MySQL中支持生成列,生成列的值是根据列定义中包含的表达式计算的。

一个简单的例子来认识生成列!

CREATE TABLE triangle(
sidea DOUBLE,
sideb DOUBLE,
sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
);

INSERT INTO triangle(sidea, sideb)  VALUES(3,4),(6,8),(5,12);

mysql> select * from triangle;  #插入数值的时候并没有插入c的值,但是查询的时候,还是有了c值
+-------+-------+-------+
| sidea | sideb | sidec |
+-------+-------+-------+
|     3 |     4 |     5 |
|     6 |     8 |    10 |
|     5 |    12 |    13 |
+-------+-------+-------+
3 rows in set (0.00 sec)

mysql>

生成列中的值,是根据生成列的定义计算出来的!

生成列的定义如下:

col_name data_type [GENERATED ALWAYS] AS (expression)
  [VIRTUAL | STORED] [NOT NULL | NULL]
  [UNIQUE [KEY]] [[PRIMARY] KEY]
  [COMMENT ‘string‘]#AS表达式表示生成列并用于计算生成列的表达式。As之前的GENERATED ALWAYS可以让生成列的性质更明确(应该没什么作用,反正是可以省略的)!#VIRTUAL | STORED 关键字表示列值的存储方式
  • VIRTUAL: 不存储列值,但在读取值之前立即计算此列的数值,虚拟列不占存储空间,innodb支持虚拟列上的二级索引。为默认的存储方式。
  • STORED:插入或更新时,将计算存储列的值,并且占用存储空间。
 生成列的表达式必须遵循以下的规则,否则会报错:
  1. 允许使用字符串,运算符和确定性内置函数。对于给定的相同的数据库,不同连接的用户调用会产生相同的结果,则这个函数时确定的。now()函数就不是确定性函数。
  2. 不允许使用子查询,参数,变量,存储函数(stored functions)和用户自定义的函数。
  3. 生成的列定义可以引用其他生成的列,但只能引用表定义中较早出现的列。生成的列定义可以引用表中的任何基本(非生成)列,无论其定义是早期还是稍后发生。
  4. auto_increment属性不能再生成列的定义中使用。
  5. 一个AUTO_INCREMENT列不能用作在生成的列定义的基柱(An AUTO_INCREMENT column cannot be used as a base column in a generated column definition.)
  6. 从MySQL 5.7.10开始,如果表达式求值导致截断或向函数提供不正确的输入,则 CREATE TABLE语句将以错误终止并拒绝DDL操作

生成列的作用(可能不太准确):

  • 虚拟生成的列可用作简化和统一查询的方法。可以将复杂条件定义为生成列,并从表上的多个查询引用,以确保他们全部使用完全相同的条件。
  • 存储生成的列可以用作物化缓存,用于复杂的条件,这些条件在运行中计算成本很高。
  • 生成列可以模拟功能索引,利用生成列定义功能表达式对其进行索引。例如对JSON数据类型。对于存储的生成列,这种方法缺点是存储两次,一次是生成列的值,另一次是索引。
  • 如果生成的列已编制索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间根据需要使用列中的索引,即使查询未按名称直接引用该列也是如此。

如下一个含有json类型字段的表:

CREATE TABLE json_test (
    id INT auto_increment PRIMARY KEY,
    userinfo json
);

#插入数据

INSERT INTO json_test(userinfo) VALUES(‘{"name":"libai","address":"china","email":"[email protected]"}‘);
INSERT INTO json_test(userinfo) VALUES(‘{"name":"obama","address":"miguo","email":"[email protected]"}‘);
INSERT INTO json_test(userinfo) VALUES(‘{"name":"putin","address":"russia","email":"[email protected]"}‘);

#

给表中添加生成列

alter table json_test add column user_name varchar(40) generated always  as (userinfo->"$.name") virtual;

#查看表中的数据
mysql> select * from json_test;
+----+--------------------------------------------------------------------+-----------+
| id | userinfo                                                           | user_name |
+----+--------------------------------------------------------------------+-----------+
|  1 | {"name": "libai", "email": "libai@163.com", "address": "china"}    | "libai"   |
|  2 | {"name": "obama", "email": "libai@gmail.com", "address": "miguo"}  | "obama"   |
|  3 | {"name": "putin", "email": "putin@gmail.com", "address": "russia"} | "putin"   |
+----+--------------------------------------------------------------------+-----------+
3 rows in set (0.00 sec)

#在表中插入数据user_name列的数值会自动计算,这时候,我们就可以对user_name列添加索引!

原文地址:https://www.cnblogs.com/wxzhe/p/9763777.html

时间: 2024-10-11 17:33:07

mysql中生成列与JSON类型的索引的相关文章

MySQL中IN子查询会导致无法使用索引

原文:MySQL中IN子查询会导致无法使用索引 今天看到一个博客园的一篇关于MySQL的IN子查询优化的案例,一开始感觉有点半信半疑(如果是换做在SQL Server中,这种情况是绝对不可能的,后面会做一个简单的测试.)随后动手按照他说的做了一个表来测试验证,发现MySQL的IN子查询做的不好,确实会导致无法使用索引的情况(IN子查询无法使用所以,场景是MySQL,截止的版本是5.7.18) MySQL的测试环境 测试表如下 create table test_table2 ( id int a

MySQL 5.7新支持--------Json类型实战

1. 背景 * 在MySQL 5.7.8中,MySQL支持由RFC 7159定义的本地JSON数据类型,它支持对JSON(JavaScript对象标记)文档中的数据进行有效访问. * MySQL会对DML JSON数据自动验证.无效的DML JSON数据操作会产生错误. * 优化的存储格式.存储在JSON列中的JSON文档转换为一种内部格式,允许对Json元素进行快速读取访问. * MySQL Json类型支持建立索引增加查询性能提升. 2. Json类型所需的存储空间和值范围 类型 占用字节

JS中生成与解析JSON

js中生成json对象 js中解析json字符串: 1.eval("..."): var a_id=eval('{"name":123}'); 如果eval中的内容含有恶意脚本就麻烦了 2.json_parse: 需要导入json_parse.js: <script src="js/json_parse.js"></script>    <script language="javascript"&

关于MySQL中的三种日期类型

Mysql中我们经常用来存储日期的数据类型有三种:Date.Datetime.Timestamp. Date数据类型用来存储没有时间的日期.Mysql获取和显示这个类型的格式为"YYYY-MM-DD".支持的时间范围为"1000-00-00"到"9999-12-31". Datetime类型存储既有日期又有时间的数据.存储和显示的格式为 "YYYY-MM-DD HH:MM:SS".支持的时间范围是"1000-00-0

mysql中生成时间维度表

利用mysql常用日期函数生成时间维度表,效率最高,最简单,无需其他的一些工具支持.生成结果示例如下图: # time span SET @d0 = "2012-01-01"; SET @d1 = "2012-12-31"; SET @date = date_sub(@d0, interval 1 day); # set up the time dimension table DROP TABLE IF EXISTS time_dimension; CREATE T

sql server 实现mysql中group_concat,列转行,列用分隔符拼接字符串

----基础 一个用户对应多个角色.role_id 为int类型使用 convert(VARCHAR,role_id)转义 ----sql: select b.user_id , roles = stuff((select ',' + convert(VARCHAR, t.ROLE_ID) from base_user_role t where b.USER_ID = t.user_id for xml path('')) , 1 , 1 , '') from base_user_role b

MySQL性能优化:MySQL中的隐式转换造成的索引失效

数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很小的疏忽造成的,又或者是因为不了解某个技术特性产生的. 于数据库层面,最常见的恐怕就是索引失效了,且一开始因为数据量小还不易被发现.但随着业务的拓展数据量的提升,性能问题慢慢的就体现出来了,处理不及时还很容易造成雪球效应,最终导致数据库卡死甚至瘫痪.造成索引失效的原因可能有很多种,相关技术博客已经有

在Mysql中遇到关于区间范围内的索引优化

上次调优Mysql 的时候,发现有些语句并没有用到索引,这引起了我的注意,发现在大数据量的情况下,由于数据的不同,会导致索引策略的更改! 通过explain命令进行查看发现结果数据过大的话type会变为index. 索引应该尽可能减少区间范围,减少结果. PS:在昨天的sql'研究中,还发现如果是select * from xxx where lat>xx and lat <xx and lng>xxx and lng <xxx更正为 select * from xxx where

关于一些 MYSQL中的字符集概念

最近遇到mysql乱码的问题,找了些资料,先保存,后面慢慢总结自己的处理方法. 笔记: 问题环境总结: 1.前台php代码没有改变 2.原数据库,所有表的都是utf8 mysql> show variables like '%char%';+--------------------------+----------------------------------+| Variable_name            | Value                            |+---