MySQL 5.7 的‘虛擬列’是做什嗎?
MySQL 5.7 中推出了一個非常實用的功能:虛擬列 Generated (Virtual) Columns。對於它的用途,我們通過一個情境來說明,假設有一個表,其中包含一個 date 類型的列
`SimpleDate` date
SimpleDate 是一個常用的查詢欄位,並需要對其執行日期函數,例如
SELECT ... WHERE dayofweek(SimpleDate) = 3 ...
此時的問題是 即使對 SimpleDate 建立索引,這個查詢語句也無法使用,因為日期函數阻止了索引
為了提高查詢效率,通常要進行額外的操作,例如建立一個欄位 SimpleDate_dayofweek,存放 dayofweek(SimpleDate) 的計算結果,然後對這列建立索引
SimpleDate_dayofweek 的值需要程式寫入,例如使用觸發器,在 SimpleDate 有變動時更新
這樣查詢就可以改為
SELECT ... WHERE SimpleDate_dayofweek = 3 ...
這麼做的好處是提高了查詢效能,可以使用 SimpleDate_dayofweek 列的索引了,但又帶來了其他麻煩,例如
(1)降低了資料寫入效能
(2)增加冗餘資料,佔用了更多的儲存空間
(3)增加代碼維護成本
虛擬列 Generated Columns 就是用來解決這個問題的,可以增加一個可被索引的列,但實際上並不存在於資料表中
對於上面的例子,可以對 SimpleDate 建立一個虛擬列,然後對虛擬列建立索引,如
CREATE TABLE `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`SimpleDate` date DEFAULT NULL,...`SimpleDate_dayofweek` tinyint(4) GENERATED ALWAYS AS (dayofweek(SimpleDate)) VIRTUAL,PRIMARY KEY (`id`),KEY `SimpleDate_dayofweek` (`SimpleDate_dayofweek`),) ENGINE=InnoDB
這樣就建好了虛擬列,此列的值不用我們計算
SELECT ... WHERE SimpleDate_dayofweek = 3 ...
查詢語句可以正常使用索引
通過虛擬列的方式,即滿足了查詢效能,也不會有之前那個解決方案的潛在麻煩
虛擬列不儲存在資料行中,但虛擬列的中繼資料資訊會存在於相關係統表中,對虛擬列的添加或者刪除只會涉及這些系統資料表,不會導致資料表的重建,所以效率很高
需要注意,不能建立虛擬列和真實列的聯合索引
本文永久更新連結地址: