新特性解讀 | MySQL 8.0 通用表達式

通用表達式在各個商業數據庫中好比ORACLE,SQL SERVER等早就實現了,MySQL到了8.0 才支持這個特性。這裏有兩個方面來舉例說明WITH的好處。mysql

第一,易用性。sql

第二,效率。數據庫

舉例一 WITH表達式的易用性

咱們第一個例子, 對比視圖的檢索和WITH的檢索。咱們知道視圖在MySQL裏面的效率一直較差,雖然說MySQL5.7 對視圖作了相關固化的優化,不過依然不盡人意。考慮下,若是屢次在同一條SQL中訪問視圖,那麼則會屢次固化視圖,勢必增長相應的資源消耗。併發

MySQL裏以前對這種消耗的減小隻有一種,就是動態處理,不過一直語法較爲噁心,使用不是很廣。app

MySQL8.0後,又有了一種減小消耗的方式,就是WITH表達式。咱們假設如下表結構:ide

| CREATE TABLE `t1` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `rank1` int(11) DEFAULT NULL,  `rank2` int(11) DEFAULT NULL,  `log_time` datetime DEFAULT NULL,  `prefix_uid` varchar(100) DEFAULT NULL,  `desc1` text,  PRIMARY KEY (`id`),  KEY `idx_rank1` (`rank1`),  KEY `idx_rank2` (`rank2`),  KEY `idx_log_time` (`log_time`)) ENGINE=InnoDB AUTO_INCREMENT=2037 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

有1000行測試記錄。函數

mysql> select count(*) from t1;+----------+| count(*) |+----------+|     1024 |+----------+1 row in set (0.00 sec)

這裏咱們創建一個普通的視圖:性能

CREATE ALGORITHM=merge SQL SECURITY DEFINER VIEW `v_t1_20` ASselect count(0) AS `cnt`,`t1`.`rank1` AS `rank1` from `t1` group by `t1`.`rank1` order by `t1`.`rank1` limit 20;


  • 檢索語句A:測試

對視圖裏的最大和最小值字段rank1進行過濾檢索出符合條件的記錄行數。大數據

mysql> use ytt;mysql> SELECT    COUNT(*)FROM    t1WHERE    rank1 = (SELECT            MAX(rank1)        FROM            v_t1_20)        OR rank1 = (SELECT            MIN(rank1)        FROM            v_t1_20);+----------+| count(*) |+----------+|       65 |+----------+1 row in set (0.00 sec)

咱們用WITH表達式來重寫一遍這個查詢。

  • 查詢語句B:

mysql> use ytt;mysql> with w_t1_20(cnt,rank1) as (SELECT    COUNT(*), rank1FROM    t1GROUP BY rank1ORDER BY rank1LIMIT 20) SELECT    COUNT(*)FROM    t1WHERE    rank1 = (SELECT            MAX(rank1)        FROM            w_t1_20)        OR rank1 = (SELECT            MIN(rank1)        FROM            w_t1_20);+----------+| count(*) |+----------+|       65 |+----------+1 row in set (0.00 sec)

個人函數不多,僅做功能性演示, 索引表面上看執行時間差很少, 咱們來對比下兩條實現語句的查詢計劃,

  • A的計劃:



  • B的計劃:


圖片

從以上圖咱們能夠看出,B比A少了一次對視圖的固化,也就是說,無論我訪問WITH多少次,僅僅固化一次。有興趣的能夠加大數據量,加大併發測試下性能。

舉例二 WITH表達式的功能性

咱們第二個例子,簡單說功能性。

好比以前MySQL一直存在的一個問題,就是臨時表不能打開屢次。咱們之前只有一種解決辦法就是把臨時表固化到磁盤,像訪問普通表那樣訪問臨時表。如今咱們能夠用MySQL8.0自帶的WITH表達式來作這樣的業務。

好比如下臨時表:

create temporary table ytt_tmp1 as SELECT    COUNT(*) cnt, rank1FROM    t1GROUP BY rank1ORDER BY rank1LIMIT 20

咱們仍是用以前的查詢,這裏會提示錯誤。

mysql> select count(*) from t1  where rank1 = (select max(rank1) from ytt_tmp1) or rank1 = (select min(rank1) from ytt_tmp1)    -> ;ERROR 1137 (HY000): Can't reopen table: 'ytt_tmp1'

如今咱們能夠用WITH來改變這種思路。

mysql> use ytt;mysql> with w_t1_20(cnt,rank1) as (SELECT    COUNT(*), rank1FROM    t1GROUP BY rank1ORDER BY rank1LIMIT 20) SELECT    COUNT(*)FROM    t1WHERE    rank1 = (SELECT            MAX(rank1)        FROM            w_t1_20)        OR rank1 = (SELECT            MIN(rank1)        FROM            w_t1_20);+----------+| count(*) |+----------+|       65 |+----------+1 row in set (0.00 sec)

固然WITH的用法還有不少,感興趣的能夠去看看手冊上的更深刻的內容。

相關文章
相關標籤/搜索