mysql 5.7 generated_MySQL 5.7新特性之Generated Column(函數索引)

官網原文:https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html

注:以下是我參考官網文檔和結合自己的理解寫的,因為英文水平有限,不排除有錯誤,歡迎糾錯。

一、說明

Generated Column是MySQL 5.7引入的新特性,所謂Cenerated Column,就是數據庫中這一列由其他列計算而得。在MySQL 5.7中,支持兩種Generated Column,即Virtual Generated Column(虛擬生成的列)和Stored Generated Column(存儲生成的列),二者含義如下:

1、Virtual Generated Column(虛擬生成的列):不存儲該列值,即MySQL只是將這一列的元信息保存在數據字典中,並不會將這一列數據持久化到磁盤上,而是當讀取該行時,觸發觸發器對該列進行計算顯示。InnoDB支持Virtual Generated Column,具體參考“https://dev.mysql.com/doc/refman/5.7/en/create-table-secondary-indexes.html”

2、Stored Generated Column(存儲生成的列):存儲該列值,即該列值在插入或更新行時進行計算和存儲。所以相對於Virtual Column列需要更多的磁盤空間,與Virtual Column相比並沒有優勢。因此,MySQL 5.7中,不指定Generated Column的類型,默認是Virtual Column

在表中允許Virtual Column和Stored Column的混合使用

提高效率:由於mysql在普通索引上加函數會造成索引失效,造成查詢性能下降,Generated Column(函數索引)剛好可以解決這個問題,可以在Generated Column加上索引來提高效率

二、創建規則

1 col_name data_type [GENERATED ALWAYS] AS(expression)2 [VIRTUAL | STORED] [NOT NULL | NULL]

3 [UNIQUE [KEY]] [[PRIMARY] KEY]4 [COMMENT 'string']

三、使用

例如,知道直角三角形的兩條直角邊,要求斜邊的長度。很明顯,斜邊的長度可以通過兩條直角邊計算而得,那么,這時候就可以在數據庫中只存放直角邊,斜邊使用Generated Column,如下所示:

-- 創建表

CREATE TABLEtriangle (

sideaDOUBLE,

sidebDOUBLE,

sidecDOUBLE AS (SQRT(sidea * sidea + sideb *sideb))

);

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

-- 查詢

mysql> SELECT * FROMtriangle;+-------+-------+--------------------+

| sidea | sideb | sidec |

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

| 1 | 1 | 1.4142135623730951 |

| 3 | 4 | 5 |

| 6 | 8 | 10 |

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

通過這個例子就足以說明Generated Columns是什么,以及怎么使用了。

注意事項:

1、可以給出其他屬性來指示該列是否被索引或可以為null,或提供注釋。

2、我們在generated column上建立索引,建立索引以后,能夠加快查找速度

索引的限制:

雖然一般情況下都應該使用Virtal Generated Column,但是,目前使用Virtual Generated Column還有很多限制

1、聚集索引不能包含virtual generated column

mysql> create table t1(a int, b int , c int GENERATED ALWAYS AS (a / b), primary key(c));

ERROR3106 (HY000): 'Defining a virtual generated column as primary key' is not supported forgenerated 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)

2、不能在Virtual Generated Column上創建全文索引和空間索引

--全文索引

mysql> CREATE TABLE`article` ( `id`int(10) unsigned NOT NULLAUTO_INCREMENT, `title`varchar(200) DEFAULT NULL, `message`varchar(200) DEFAULT NULL, `content`text GENERATED ALWAYS AS(concat(`title`,`message`)),PRIMARY KEY(`id`), FULLTEXTKEY`content_idx1` (`content`) ) ;[Err] 3106 - 'Fulltext index on virtual generated column' is not supported forgenerated columns.--全文索引 mysql>CREATE TABLE`article` ( `id`int(10) unsigned NOT NULLAUTO_INCREMENT, `title`varchar(200) DEFAULT NULL, `message`varchar(200) DEFAULT NULL, `content`text GENERATED ALWAYS AS(concat(`title`,`message`)) STORED,PRIMARY KEY(`id`), FULLTEXTKEY`content_idx1` (`content`) ) ; Query OK,0 rows affected (0.11 sec)

3、Virtual Generated Column不能作為外鍵

4、創建generated column(包括virtual generated column 和stored generated column)時可以使用確定性內置函數和運算符,但不能使用非確定性的(不可重復的)函數。

mysql> ALTER TABLE `score` ADD deal_time DATE GENERATED ALWAYS AS(now()) virtual;[Err] 3102 - Expression of generated column 'deal_time' contains a disallowed function.

mysql> ALTER TABLE `score` ADD deal_time DATE GENERATED ALWAYS AS(now()) stored;[Err] 3102 - Expression of generated column 'deal_time' contains a disallowed function.

5、子查詢、參數、變量和用戶定義的函數都是不允許的

四、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的函數索引,似乎代價會高很多。但是,我們在上面提過,對於Virtual Generated Column,MySQL只是將這一列的元信息保存在數據字典中,並不會將這一列數據持久化到磁盤上,因此,在MySQL的Virtual Generated Column上建立索引和Oracle的函數索引類似,並不需要更多的代價,只是使用方式有點不一樣而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值