mysql虛擬列(Generated Columns)及JSON欄位型別的使用
mysql 5.7中有很多新的特性,但平時可能很少用到,這裡列舉2個實用的功能:虛擬列及json欄位型別
一、先建立一個測試表:
1 2 3 4 5 6 7 8 9 |
(3),
|
注:這裡profile是一個json型別的欄位,另db編碼採用utf8mb4
二、生成測試資料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
"\",\"age\":" ,i, "}" );
|
注:這段儲存過程不是本文重點,看不懂的同學不用深研,大概意思就是name隨機生成,profile隨機生成一個類似{"phone":"13xxxxxx","age":x}的內容。
呼叫一下這個儲存過程,生成100000條測試資料,資料大致長下面這樣:
需求來了,假如我們要查姓“張”的人有多少個?
這顯然是一個全表掃描!
三、字首索引
肯定有同學想到了,在name上建一個字首索引,只對name的第1個字做索引
1 |
|
確實是個好辦法,效果也不錯
但是需求總是變化的,如果想查第2個字是“楊”的人有多少?
依然會全表掃描。
四、虛擬列
1 |
|
建立了一個虛擬列second_name,其值是substring(name,2,1),即name中的第2個字,最後的stored表示,資料寫入時這個列的值就會計算(詳情可參考最後的參考連結)
注:虛擬列並不是真正的列,insert時也無法指定欄位值。
然後在這個列上建立索引:
1 |
|
再來看下執行計劃,索引生效了,掃描行數也明顯下降。
當然,sql語句也可以改成:
1 |
|
這樣看上去更直觀,效果不變。
五、json檢索
又來新需求了:要查profile中手機號為13589135467,並且姓“吳”的人
注意:profile->"$.phone"=xxx 就是json欄位的檢索語法
分析執行計劃,可以看到字首索引“ix_name”生效了,但還有優化空間,仍然可以藉助虛擬列,建立2個虛擬列phone、first_name,並建立聯合索引。
1 2 3 |
|
加了這2個虛擬列後,資料長這樣:
注:phone列提取出來後,前後會帶上引號。
剛才的需求,可以改寫sql:
1 |
|
最後看下執行計劃:
掃描行數下降到個位數,效果十分明顯。
參考文章:
http://mysqlserverteam.com/generated-columns-in-mysql-5-7-5/