MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的、完整的教程。这篇文章围绕以下几个问题展开:

Generated Column是什么  
Virtual Column与Stored Column的区别  
如果我对Generated Column做一些破坏行为会怎么样  
Generated Column上创建索引  
Generated Column上创建索引与Oracle的函数索引的区别

Generated Column是什么

Generated Column是MySQL 5.7引入的新特性,所谓Cenerated Column,就是数据库中这一列由其他列计算而得,我们以官方参考手册中的例子予以说明。

例如,知道直角三角形的两条直角边,要求斜边的长度。很明显,斜边的长度可以通过两条直角边计算而得,那么,这时候就可以在数据库中只存放直角边,斜边使用Generated Column,如下所示:

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

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

查询结果:

mysql> SELECT * FROM triangle;  
+-------+-------+--------------------+  
| sidea | sideb | sidec |  
+-------+-------+--------------------+  
| 1 | 1 | 1.4142135623730951 |  
| 3 | 4 | 5 |  
| 6 | 8 | 10 |  
+-------+-------+--------------------+

这个例子就足以说明Generated Columns是什么,以及怎么使用用了。

Virtual Generated Column与Stored Generated Column的区别

在MySQL 5.7中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column,前者只将Generated Column保存在数据字典中(表的元数据),并不会将这一列数据持久化到磁盘上;后者会将Generated Column持久化到磁盘上,而不是每次读取的时候计算所得。很明显,后者存放了可以通过已有数据计算而得的数据,需要更多的磁盘空间,与Virtual Column相比并没有优势,因此,MySQL 5.7中,不指定Generated Column的类型,默认是Virtual Column。此外:  #p#分页标题#e#
Stored Generated Column性能较差,见这里  
如果需要Stored Generated Golumn的话,可能在Generated Column上建立索引更加合适,见本文第4部分的介绍

综上,一般情况下,都使用Virtual Generated Column,这也是MySQL默认的方式,如果使用Stored Generated Column,前面的建表语句将会是下面这样,即多了一个stored关键字:

Create Table: CREATE TABLE `triangle` (  
 `sidea` double DEFAULT NULL,  
 `sideb` double DEFAULT NULL,  
 `sidec` double GENERATED ALWAYS AS (SQRT(sidea * sidea + sideb * sideb)) STORED)

如果对generated column做一些破坏行为会怎么样?

我们已经知道了generated column是什么,并且知道了如何使用generated column,为了避免误用,我们先来进行一些实验,以免在具体使用时出现一些未知的情况。

将generated column定义为 "除以0"

如果我们将generated column定义为 "x列 / 0",MySQL并不会直接报错,而是在插入数据时报错,并提示"ERROR 1365 (22012): Division by 0"  
  
mysql> create table t( x int, y int, z int generated always as( x / 0));  
Query OK, 0 rows affected (0.22 sec)  
  
mysql> insert into t(x,y) values(1,1);  
ERROR 1365 (22012): Division by 0

插入恶意数据  
如果我们将generated column定义为 "x列/y列",在插入数据,如果y列为0的话,同样提示错误,如下所示:

mysql> create table t( x int, y int, z int generated always as( x / y));  
Query OK, 0 rows affected (0.20 sec)

mysql> insert into t(x,y) values(1,0);  
ERROR 1365 (22012): Division by 0

删除源列  
  
如果我们将generated column定义为 "x列/y列",并尝试删除x列或y列,将提示"ERROR 3108 (HY000): Column 'x' has a generated column dependency."

mysql> create table t( x int, y int, z int generated always as( x / y));  #p#分页标题#e#
Query OK, 0 rows affected (0.24 sec)

mysql> alter table t drop column x;  
ERROR 3108 (HY000): Column 'x' has a generated column dependency.

定义显然不合法的Generated Column  
  
如果我们将generated column定义为 "x列+y列",很明显,x列或y列都是数值型,如果我们将x列或y列定义(或修改)为字符型(当然,实际使用时应该不会有人傻到这样去做),则预期会报错,然而并没有,如下所示,我们可以正常创建。

mysql> create table t( x int, y varchar(100), z int generated always as( x + y));  
 Query OK, 0 rows affected (0.13 sec)

并且插入如下这样的数据也不会出错:

mysql> insert into t(x,y) values(1,'0');  
Query OK, 1 row affected (0.01 sec)

mysql> select * from t;  
+------+------+------+  
| x | y | z |  
+------+------+------+  
| 1 | 0 | 1 |  
+------+------+------+  
1 row in set (0.00 sec)

但是对于MySQL无法处理的情况,则会报错:

mysql> insert into t(x,y) values(1,'x');  
ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'x'

Generated Column上创建索引

同样,我们可以在generated column上建立索引,建立索引以后,能够加快查找速度,如下所示:

mysql> create table t(x int primary key, y int, z int generated always as (x / y), unique key idz(z));  
Query OK, 0 rows affected (0.11 sec)

mysql> show create table t\G  
*************************** 1. row ***************************  
Table: t  
Create Table: CREATE TABLE `t` ( 
  `x` int(11) NOT NULL, 
  `y` int(11) DEFAULT NULL, 
  `z` int(11) GENERATED ALWAYS AS (x / y) VIRTUAL, 
  PRIMARY KEY (`x`), #p#分页标题#e#
  UNIQUE KEY `idz` (`z`)) ENGINE=InnoDB DEFAULT CHARSET=latin1  
1 row in set (0.01 sec)

并且,我们可以创建普通索引和唯一索引,如果是唯一索引,在违反了唯一性约束时,进行报错:

mysql> insert into t(x,y) values(1,1);  
Query OK, 1 row affected (0.02 sec)

mysql> insert into t(x,y) values(2,2);  
ERROR 1062 (23000): Duplicate entry '1' for key 'idz'

所以,在使用MySQL5.7时,还需要对Generated Column有所了解,才能够解决一些以前没有遇到过的问题。  
 
索引的限制  
虽然一般情况下都应该使用Virtal Generated Column,但是,目前使用Virtual Generated Column还有很多限制,包括:

聚集索引不能包含virtual generated column

mysql> create table t1(a int, b int , c int GENERATED ALWAYS AS (a / b), primary key(c));  
ERROR 3106 (HY000): 'Defining a virtual generated column as primary key' is not supported for generated columns.

mysql> create table t1(a int, b int , c int GENERATED ALWAYS AS (a / b) STORED, primary key(c));  
Query OK, 0 rows affected (0.11 sec)

不能在Virtual Generated Column上创建全文索引和空间索引,这个在之后的MySQL版本中有望解决(Inside君咋记得Stored Column上市可以的呢?)。

Virtual Generated Column不能作为外键

创建generated column(包括virtual generated column 和stored generated column)时不能使用非确定性的(不可重复的)函数

mysql> ALTER TABLE `t1` ADD p3 DATE GENERATED ALWAYS AS (curtime()) virtual;  
ERROR 3102 (HY000): Expression of generated column 'p3' contains a disallowed function.

mysql> ALTER TABLE `t1` ADD p3 DATE GENERATED ALWAYS AS (curtime()) stored;  
ERROR 3102 (HY000): Expression of generated column 'p3' contains a disallowed function. #p#分页标题#e#

Generated Column上创建索引与Oracle的函数索引的区别  
介绍完MySQL在Generated Column上的索引,熟悉Oracle的同学这时候可能会想起Oracle的函数索引,在MySQL的Generated Column列上建立索引与Oracle的函数索引比较类似,又有所区别:

例如有一张表,如下所示:

mysql> CREATE TABLE t1 (first_name VARCHAR(10), last_name VARCHAR(10));  
Query OK, 0 rows affected (0.11 sec)

假设这时候需要建一个full_name的索引,在Oracle中,我们可以直接在创建索引的时候使用函数,如下所示:

alter table t1 add index full_name_idx(CONCAT(first_name,' ',last_name));

但是,上面这条语句在MySQL中就会报错。在MySQL中,我们可以先新建一个Generated Column,然后再在这个Generated Column上建索引,如下所示:

mysql> alter table t1 add column full_name VARCHAR(255) GENERATED ALWAYS AS (CONCAT(first_name,' ',last_name));

mysql> alter table t1 add index full_name_idx(full_name);

乍一看,MySQL需要在表上增加一列,才能够实现类似Oracle的函数索引,似乎代价会高很多。但是,我们在第2部分说过,对于Virtual Generated Column,MySQL只是将这一列的元信息保存在数据字典中,并不会将这一列数据持久化到磁盘上,因此,在MySQL的Virtual Generated Column上建立索引和Oracle的函数索引类似,并不需要更多的代价,只是使用方式有点不一样而已。

转载于:http://www.itxuexiwang.com/a/shujukujishu/2016/0302/199.html?1457018327

MySQL 5.7新特性之Generated Column(函数索引)的更多相关文章

  1. MySQL 5.7新特性之generated column

    MySQL 5.7引入了generated column,这篇文章简单地介绍了generated column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...

  2. MySQL 8.0 新特性梳理汇总

    一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...

  3. [转帖 ]MySQL 5.7 新特性 JSON

    MySQL 5.7 新特性 JSON 的创建,插入,查询,更新 作者: 我不是鱼 (2016-08-31 16:13)分类: MySQL   标签: MySQL JSON MySQL JSON 应用 ...

  4. Mysql 8.0 新特性测试

    Mysql 8.0 新特性测试 Role MySQL8.0版本添加了role特性,role是一种逻辑概念是权限的集合,可以将一个或以上的权限赋予给role,再将role赋给user.Oracle,Po ...

  5. mysql 5.7 ~ 新特性

    mysql 5.7特性 简介:mysql 5.7内存和线程性能方面的优化一 细节优化 参数:  1 innodb_buffer_pool    改进 innodb_buffer_pool可以动态扩大, ...

  6. MySql 5.7 新特性概览

    安全的提升 1.1 在Mysql 8版本中,caching_sha2_password 是一个缺省的认证插见.5.7 版本的客户端支持 caching_sha2_password 的客户端认证. 1. ...

  7. 初识 MySQL 5.6 新特性、功能

    背景: 之前介绍过 MySQL 5.5 新功能.参数,现在要用MySQL5.6,所以就学习和了解下MySQL5.6新的特性和功能,尽量避免踩坑.在后续的学习过程中文章也会不定时更新. 一:参数默认值的 ...

  8. MySQL 5.6新特性 -- Multi-Range Read

    如果基表很大,数据没有被缓存,在二级索引上使用范围扫描读取行可能会导致大量的随机磁盘访问.使用Multi-Range Read新特性,mysql可以减少对磁盘的随机读的次数:首先,mysql只是扫描索 ...

  9. 总结一下关于mysql 5.6 新特性

    一直断断续续的看一些mysql特性,今天总结一下,以下是列表,网址 http://mariadb.org/ (也是类似的特性), http://mysql.com/ 最近在看关于mysql新特性的一些 ...

随机推荐

  1. 增强拉格朗日乘子法(Augmented Lagrange Method)

    增强拉格朗日乘子法的作用是用来解决等式约束下的优化问题, 假定需要求解的问题如下: minimize f(X) s.t.: h(X)=0 其中,f:Rn->R; h:Rn->Rm 朴素拉格 ...

  2. appium踩过的坑(1):NoClassDefFoundError

    1.引入jar包错误导致的错误: 引入的jar包引起的 应该引入下面的jar包

  3. 通过实现Countable接口来调用count函数

    周六我一大早就来到公司,还有些客户工作没有收尾,还有写文档没写,还有写计划需要完善,我得抓紧.到了下午我发现大家陆陆续续的都到公司来了,有几个兄弟一来就开始工作了,每当有人自愿投入某一项工作时,我基本 ...

  4. ORACLE 自动增长通过封装函数,方便调用

    好的编程习惯,是一个很有必要的过程.好的编程习惯,可以因人而异,但是简单地.基本地代码级别的就那些:写注释.合理的缩进.换行.变量命名等. 对我们程序员来说,大部分时间都对着电脑,在对着电脑的大部分时 ...

  5. 最喜欢的算法(们) - Levenshtein distance

    String Matching: Levenshtein distance Purpose: to use as little effort to convert one string into th ...

  6. P 1080 Human Gene Functions

    大概作了一周,终于A了 类似于求最长公共子序列,稍有变形 当前序列 ch1 中字符为 a,序列 ch2 中字符为 b 则有 3 种配对方式: 1. a 与 b 2. a 与 - 3. - 与 b 动态 ...

  7. Nutch2+Hbase环境部署和基本使用

    由于项目想借助Nutch来做网络爬虫,所以一番研究,发现网上文档比较散,学习的很艰难,因此总结了一些,放上来与大家交流. 1       环境部署 Nutch有1.x系列和2.x系列,主要区别是2.x ...

  8. C# final project

    Problem Statement You are tasked with developing a task manager. The task manager will allow people ...

  9. Drupal资源

    以下是一些Drupal的常用资源. www.drupal.org:Drupal官网,拥有最全 www.acquia.com:Drupal奠基人Dries主导的专业网站,有著名的Aquia平台,功能类似 ...

  10. C++ 非阻塞套接字的使用 (3)

    异步非阻塞套接字避免了死循环的接收问题,但是软件用起来体验还是很差.究其原因,软件在指令的发送.接收上, 采取了一种不合理的方式:在指令的发送后,立刻调用接收函数,等待回令. 若是采用同步阻塞套接字, ...