[MySQL 5.7.6] Generated Column

updated @2015-08-09, mysql-5.7.8-rc对generated column的改进:

    • InnoDB: InnoDB now supports secondary indexes on virtual generated columns. For more information, seeCREATE TABLE and Generated Columns.
    • InnoDB: Virtual generated column values no longer occupy space in database rows. With this change, a table rebuild is no longer required when adding or dropping virtual generated columns.

      Virtual generated columns are still represented in InnoDB metadata. TheN_COLS field of INNODB_SYS_TABLESstill counts virtual generated columns, and INNODB_SYS_COLUMNS still includes virtual generated column metadata.

      A new INFORMATION_SCHEMA table, INNODB_SYS_VIRTUAL, provides metadata about columns upon which virtual generated columns are based

相关连接:

Worklog: http://dev.mysql.com/worklog/task/?id=411

官方文档: http://dev.mysql.com/doc/refman/5.7/en/create-table.html#create-table-generated-columns

最初的代码似乎是从6.0版本port过来的? git show fb6b2848770dd67f12de00414ebf58fd1601fa9b …这个git可以辅助理解主要的修改点,但和最终代码相差很大,感兴趣的可以git log 搜索WL#411找到对应的补丁。

简单介绍

从MySQL 5.7.6开始支持Generated Column这个特性。所谓generated column,就是在CREATE或ALTER TABLE时,可以通过表达式的方式定义的新的列类型,表达式可以选择虚拟的(在读取时产生)或者物化的(在插入或更新时自动计算并存储到文件中)。

列定义的语法如下:

col_name data_type [GENERATED ALWAYS] AS (expression)
 [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
 [[NOT] NULL] [[PRIMARY] KEY]

AS后面的expression就是你定义的表达式。也不是任何表达式都可以定义,需要满足一定的条件,如下:

  • 允许内建的具有确定性的函数和操作,但不允许类似CURRENT_TIMESTAMP这样的不确定表达式
  • 不允许的表达式:Subqueries, parameters, variables, stored functions, user-defined functions.
  • 可以引用预先已经定义的其他GC列
  • 允许使用STORED GC列来进行分区,但不允许被触发器引用。(使用GC列来进行分区可以绕过分区表对函数分区的限制)
  • 可以增加/删除GC列,但不能将其转换成普通列
  • 当尝试更改一个有GC依赖的列名时会报错。
  • 可以in-place修改VIRTUAL的GC列,但不能IN-PLACE修改STORED的GC列

另外两个关键字VIRTUAL 和STORED定义了列是否存储到实际文件中。默认为VIRTUAL。

举几个简单的例子:

create table t1 (a int, b int,c int as (a+b) , d int as (a+b+c) stored key) engine = innodb;

insert into t1(a,b) values (1,2),(2,3),(3,4);

root@test 04:07:51>select c,d from t1;
+——+—-+
| c | d |
+——+—-+
| 3 | 6 |
| 5 | 10 |
| 7 | 14 |
+——+—-+
3 rows in set (0.00 sec)

root@test 05:25:02>select COLUMN_NAME, EXTRA, GENERATION_EXPRESSION from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = ‘test’ and table_name = ‘t1’\G
*************************** 1. row ***************************
COLUMN_NAME: a
EXTRA:
GENERATION_EXPRESSION:
*************************** 2. row ***************************
COLUMN_NAME: b
EXTRA:
GENERATION_EXPRESSION:
*************************** 3. row ***************************
COLUMN_NAME: c
EXTRA: VIRTUAL GENERATED
GENERATION_EXPRESSION: a+b
*************************** 4. row ***************************
COLUMN_NAME: d
EXTRA: STORED GENERATED
GENERATION_EXPRESSION: a+b+c
4 rows in set (0.01 sec)

root@test 05:25:35>create table t2 (a int , b int ,c timestamp as (CURRENT_TIMESTAMP));
ERROR 3102 (HY000): Expression of generated column ‘c’ contains a disallowed function.

Generated Column可以协助我们实现之前在SQL中的复杂的计算逻辑,简化SQL。而物化存储的Genrated Column相当于帮助我们将需要复杂计算得到的结果存储起来,无需每次重复计算,从而减少CPU开销。你甚至还可以对generated column进行索引 (Tips:目前5.7.6版本的stored的generated column如果定义为索引的话,会自动转换为Primary key,已有人report到buglist了)

代码实现

主要包括:

1.语法支持,主要修改sql_yacc.yy文件

2.检查合法性:Create_field::init、mysql_prepare_create_table

3.对于VIRTUAL GC列,读取数据时需要更新GC列值(handler::ha_rnd_next –> update_generated_read_fields)

4.对于STORED GC列,写入或更新数据时需要生成GC列的值(Sql_cmd_insert::mysql_insert –)

INSERT:Sql_cmd_insert::mysql_insert –> fill_record_n_invoke_before_triggers –> fill_record –> update_generated_write_fields

UPDATE:Sql_cmd_update::try_single_table_update –> mysql_update –> fill_record_n_invoke_before_triggers –> fill_record –> update_generated_write_fields

5.show create table需要显示新的表定义方式:store_create_info

6.增加了一种新的语法类型PARSE_GCOL_EXPR(PARSE_GCOL_KEYWORD, 由MySQL Server使用)来辅助将从frm中读取的GC列表达式转换成Item,函数:open_table_from_share –> unpack_gcol_info_from_frm

7.打开frm文件时需要提取存储的表达式:open_binary_frm

8.引擎层基本没啥变化,因为VIRTUAL的GC列计算都在server层,STORED GC列则当作真正的列进行存储。但是依然会为VIRTUAL的GC列在引擎层预留列的位置,只是不写入任何数据。由于VIRTUAL GC列的field->store_in_db标识为FALSE, InnoDB在比较列修改时,可以根据标识直接忽略掉:calc_row_difference

时间: 2024-08-02 10:22:12

[MySQL 5.7.6] Generated Column的相关文章

数据库-mysql查询出现1054 Unknown column错误

问题描述 mysql查询出现1054 Unknown column错误 1 queries executed, 0 success, 1 errors, 0 warnings 查询:select * from orders where oid=1a0b3ae07ae74b08872fa140a5f805f0 LIMIT 0, 1000 错误代码: 1054 Unknown column '1a0b3ae07ae74b08872fa140a5f805f0' in 'where clause' 有人

MySQL数据库-错误1166 Incorrect column name_Mysql

出现MySQL数据库-错误1166 Incorrect column name 字段名,这个是字段中有空格了,这个只要利用alert或phpmyadmin进入修改即可解决. 今天在用Navicat for MySQL给MySQL数据库修改表的字段时报如下的错误 SQL 查询: CREATE TABLE `gfan_content`.`channel_into` ( `time` INT( 11 ) NOT NULL COMMENT '产品id', `bid` INT( 11 ) NOT NULL

MySQL数据库-错误1166 Incorrect column name

今天在用Navicat for MySQL给MySQL数据库修改表的字段时报如下的错误 SQL 查询: CREATE TABLE `gfan_content`.`channel_into` ( `time` INT( 11 ) NOT NULL COMMENT '产品id', `bid` INT( 11 ) NOT NULL COMMENT '渠道商id' ) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci; MySQL 返回

Mysql错误Operand should contain * column解决办法

使用了sql语句处理某些内容.当执行某个语句时,Mysql报错误:Operand should contain 1 column 字面意思是,需要有1个数据列. 我的sql语句类似这样: update cdtable set cdcontent='cd is a good boy' where id in( select * from( select * from cdtable where cdtype in(1,2,3) order by id desc limit 100 )as cd )

mysql下count(*)与count(column)区别性能对比

count(*)对行的数目进行计算,包含NULL count(column)对特定的列的值具有的行数进行计算,不包含NULL值. count()还有一种使用方式,count(1)这个用法和count(*)的结果是一样的. 关于他们的性能问题 1.任何情况下SELECT COUNT(*) FROM tablename是最优选择: 2.尽量减少SELECT COUNT(*) FROM tablename WHERE COL = 'value' 这种查询: 3.杜绝SELECT COUNT(COL)

MySQL 5.7 新特性 generated columns

MySQL 5.7的一个新特性,generated column http://dev.mysql.com/doc/refman/5.7/en/create-table.html#create-table-generated-columns 即generated column的值是普通column产生值,有点像视图,但是又有别于视图,因为它可以选择是否存储generated column产生的值. CREATE TABLE triangle ( sidea DOUBLE, sideb DOUBL

MySQL · 引擎特性 · Column Compression浅析

前言 当用户的数据量比较大时,通常需要对数据进行压缩,以减少磁盘占用.InnoDB目前有两种方式来实现这一目的. 第一种是传统的数据压缩,通过指定row_format及key_block_size,能够将用户表压缩到指定的page size并进行存储,默认使用zlib.这种压缩方式使用比较简单,但也是诟病较多的, 代码陈旧,相关代码基本上几个大版本都没发生过变化,一些优化点还是从facebook移植过来的(集中在5.6版本中, 不过现在fb已经放弃优化InnoDB压缩了,转而聚集在自家压缩更好的

MySQL · 引擎特性 · 像NOSQL那样使用MySQL

前言 最近Release的MySQL5.7.12增加了新的协议支持,通过X Plugin实现,同时增加了新的客户端API,开发者可以通过API来把MySQL作为document store的服务端,可以完成和MongoDB类似的document操作,例如支持CRUD等操作,但底层存储依然支持传统数据库的ACID,操作本身在底层也被扩展成标准SQL.从目前的MySQL来看,NOSQL和传统数据库的界限越来越小.目前这个特性还未Production Ready,建议仅用于测试环境. 本文只是记录下学

数据库内核月报 - 2015 / 11-MySQL · 社区见闻 · OOW 2015 总结 MySQL 篇

前言 && 感想 本年度Oralce Open World会议从十月25号到29号,在美国旧金山举行.数万来自全球各地的从业人员涌入Moscone Center,见证一年一度的Oracle生态系统盛事. 本次OOW2015的主题都是围绕在Oracle Cloud,云服务应该是Oracle之后的发力点.几场Oracle CTO(前Oracle CEO)Larry的主题演讲也围绕cloud,详细阐述了Oracle Cloud的设计原则,及相关的云产品,其目标直指Amazon和Microsoft