新特性解读 | MySQL 8.0 通用表达式

原创: 杨涛涛


 

通用表达式在各个商业数据库中比如ORACLE,SQL SERVER等早就实现了,MySQL到了8.0 才支持这个特性。这里有两个方面来举例说明WITH的好处。

第一,易用性。

第二,效率。

 

举例一 WITH表达式的易用性

我们第一个例子, 对比视图的检索和WITH的检索。我们知道视图在MySQL里面的效率一直较差,虽说MySQL5.7 对视图做了相关固化的优化,不过依然不尽人意。考虑下,如果多次在同一条SQL中访问视图,那么则会多次固化视图,势必增加相应的资源消耗。

MySQL里之前对这种消耗的减少只有一种,就是动态处理,不过一直语法较为恶心,使用不是很广。

MySQL8.0后,又有了一种减少消耗的方式,就是WITH表达式。我们假设以下表结构:

| 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` AS
select 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
t1
WHERE
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(*), rank1
FROM
t1
GROUP BY rank1
ORDER BY rank1
LIMIT 20
) SELECT
COUNT(*)
FROM
t1
WHERE
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, rank1
FROM
t1
GROUP BY rank1
ORDER BY rank1
LIMIT 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(*), rank1
FROM
t1
GROUP BY rank1
ORDER BY rank1
LIMIT 20
) SELECT
COUNT(*)
FROM
t1
WHERE
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的用法还有很多,感兴趣的可以去看看手册上的更深入的内容。

转载于:https://my.oschina.net/actiontechoss/blog/3069550

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
限时福利1:购课进答疑群专享柳峰(刘运强)老师答疑服务 为什么需要掌握高性能的MySQL实战? 由于互联网产品用户量大、高并发请求场景多,因此对MySQL的性能、可用性、扩展性都提出了很高的要求。使用MySQL解决大量数据以及高并发请求已经是程序员的必备技能,也是衡量一个程序员能力和薪资的标准之一。 为了让大家快速系统了解高性能MySQL核心知识全貌,我为你总结了「高性能 MySQL 知识框架图」,帮你梳理学习重点,建议收藏! 【课程设计】 课程分为四大篇章,将为你建立完整的 MySQL 知识体系,同时将重点讲解 MySQL 底层运行原理、数据库的性能调优、高并发、海量业务处理、面试解析等。 一、性能优化篇: 主要包括经典 MySQL 问题剖析、索引底层原理和事务与锁机制。通过深入理解 MySQL 的索引结构 B+Tree ,学员能够从根本上弄懂为什么有些 SQL 走索引、有些不走索引,从而彻底掌握索引的使用和优化技巧,能够避开很多实战中遇到的“坑”。 二、MySQL 8.0新特性篇: 主要包括窗口函数和通用表达式。企业中的许多报表统计需求,如果不采用窗口函数,用普通的 SQL 语句是很难实现的。 三、高性能架构篇: 主要包括主从复制和读写分离。在企业的生产环境中,很少采用单台MySQL节点的情况,因为一旦单个节点发生故障,整个系统都不可用,后果往往不堪设想,因此掌握高可用架构的实现是非常有必要的。 四、面试篇: 程序员获得工作的第一步,就是高效的准备面试,面试篇主要从知识点回顾总结的角度出发,结合程序员面试高频MySQL问题精讲精练,帮助程序员吊打面试官,获得心仪的工作机会。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值