優化體系--詳解MySQL 5.7虛擬列,值得收藏

2019-07-28     波波說運維

概述

我們都知道where條件如果在欄位上帶了函數就不會去走索引,不好優化,無意間了解到mysql一個新特性--虛擬列,專門處理這塊問題的,下面一起來了解下吧~


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。

如果需要Stored Generated Golumn的話,可能在Virtual Generated Column上建立索引更加合適。綜上,一般情況下,都使用Virtual Generated Column,這也是MySQL默認的方式


語法

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

應用場景

假設有一個表,其中包含一個 date 類型的列 `SimpleDate` date

SimpleDate 是一個常用的查詢欄位,並需要對其執行日期函數,例如

SELECT ... WHERE dayofweek(SimpleDate) = 3 ...

此時的問題是 即使對 SimpleDate 建立索引,這個查詢語句也無法使用,因為日期函數阻止了索引。

為了提高查詢效率,通常要進行額外的操作,例如新建一個欄位 SimpleDate_dayofweek,存放 dayofweek(SimpleDate) 的計算結果,然後對這列創建索引,SimpleDate_dayofweek 的值需要程序寫入,例如使用觸發器,在 SimpleDate 有變動時更新這樣查詢就可以改為

SELECT ... WHERE SimpleDate_dayofweek = 3 ...

這麼做的好處是提高了查詢性能,可以使用 SimpleDate_dayofweek 列的索引了,但又帶來了其他麻煩,例如

  • 降低了數據寫入性能
  • 增加冗餘數據,占用了更多的存儲空間
  • 增加代碼維護成本

虛擬列 Generated Columns 就是用來解決這個問題的,可以增加一個可被索引的列,但實際上並不存在於數據表中,下面用一個實驗來說明下:


實驗

需求:為了實現對json數據中部分數據的索引查詢,考慮用MySQL5.7中的虛擬列功能

1、創建表

create table user(uid int auto_increment,data json,primary key(uid));

2、準備數據

insert into user values (NULL,'{"name":"hwb","address":"guangzhou"}');
insert into user values (NULL,'{"name":"tqy","address":"shenzhen"}');
commit;

3、構建姓名的虛擬列

alter table user add user_name varchar(20) generated always as (data->'$.name');

4、構建索引

alter table user add index idx_name(user_name);

5、測試是否用到索引

explain select * from user where user_name='"hwb"' \\G;

可以看出用了索引了

6、插入新數據

此時的表的結構由於多出了user_name這一虛擬列,再插入別的數據要注意在表後指明插入列(不能給虛擬列插入數據)

insert into user(uid,data) values (NULL,'{"name":"test","address":"shantou"}');


做完發現這個實驗好像不是那麼好理解...應該對比一下加不加虛擬列有沒走索引,可能會更容易讓大家理解的...後面會分享更多devops和DBA方面的內容,感興趣的朋友可以關注一下~

文章來源: https://twgreatdaily.com/jd-q1GwBJleJMoPMWdPm.html