构建测试数据
create table test_1
(
sname varchar(10),
score int
);
insert into test_1
select '张三',80 union all
select '李四',90 union all
select '王五',50 union all
select '陈二',70;
复制
先看一下版本
SELECT @@VERSION
复制
5.6.16-log
执行如下语句
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
) t2 where score >60;
复制
-------以上结果 在5.6版本中完全正确
我们切换到8.0版本
select @@version
复制
8.0.25
同样构造上述的测试数据
再执行同样的语句
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
) t2 where score >60
复制
what?? 为什么得到的sort_i 是1,2,3?
我们来看优化器改写的语句
explain
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
) t2 where score >60
show warnings;
复制
发现优化器 改写了我们的语句
/* select#1 */ select `t2`.`sort_i` AS `sort_i`,`t2`.`sname` AS `sname`,`t2`.`score` AS `score`
from (/* select#2 */ select (@i1:=((@`i1`) + 1)) AS `sort_i`,`sys`.`test_1`.`sname` AS `sname`,`sys`.`test_1`.`score` AS `score` from `sys`.`test_1` where (`sys`.`test_1`.`score` > 60)) `t2`
复制
把外层嵌套干掉了。
我先不说mysql8.0的解决办法。
再回头看看5.6版本优化器改写的后。
explain extended
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
) t2 where score >60;
show warnings;
复制
得到优化器改写后的语句
/* select#1 */ select `t2`.`sort_i` AS `sort_i`,`t2`.`sname` AS `sname`,`t2`.`score` AS `score`
from (/* select#2 */ select (@i1:=((@`i1`) + 1)) AS `sort_i`,`userdb0001`.`test_1`.`sname` AS `sname`,`userdb0001`.`test_1`.`score` AS `score` from `userdb0001`.`test_1`) `t2` where (`t2`.`score` > 60)
复制
发现在5.6版本,没有将我的外部条件推入派生表优化
8.0版本有两种解方案:
第一种 修改参数配置
MySQL 8.0.22开始,新增了 optimizer_switch 参数,新增了 derived_condition_pushdown 变量
启⽤用该变量后,可能会导致最外层 where 条件中使⽤了⽤户变量的 SQL 语句得到⾮预期的结果
该变量的主要作用是。将个外层条件下推到派生表中,让派生表返回的行数减少,以达到优化。
我们将优化参数改掉看结果
set optimizer_switch='derived_condition_pushdown=off';
复制
然后再执行
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
) t2 where score >60
复制
结果变正确了。
第二种方案是 即然8.0优化器要改写我们的语句,我们就不让它改。因为mysql 派生优化在某些特定条件下是不会进行的
查询资料得到 当派生表内有如下操作时,将不会进行优化
DISTINCT
GROUP BY
HAVING
LIMIT
UNION 或者 UNION ALL
在这里。我们加上一个limit 让mysql不自动优化
select * from
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select @i1:= 0) t1
limit 100
) t2 where score >60
复制
结果也变正确了。
最后修改时间:2021-11-30 08:45:12
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
您好,您的文章已入选合格奖,10墨值奖励已经到账请查收!
❤️我们还会实时派发您的流量收益。
3年前

评论
相关阅读
【MySQL 30周年庆】MySQL 8.0 OCP考试限时免费!教你免费领考券
墨天轮小教习
897次阅读
2025-04-25 18:53:11
MySQL 30 周年庆!MySQL 8.4 认证免费考!这次是认真的。。。
严少安
543次阅读
2025-04-25 15:30:58
墨天轮个人数说知识点合集
JiekeXu
454次阅读
2025-04-01 15:56:03
MySQL数据库当前和历史事务分析
听见风的声音
434次阅读
2025-04-01 08:47:17
MySQL 生产实践-Update 二级索引导致的性能问题排查
chengang
395次阅读
2025-03-28 16:28:31
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
373次阅读
2025-04-17 17:02:24
MySQL 9.3 正式 GA,我却大失所望,新特性亮点与隐忧并存?
JiekeXu
359次阅读
2025-04-15 23:49:58
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
337次阅读
2025-04-15 14:48:05
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
309次阅读
2025-04-07 12:14:29
记录MySQL数据库的一些奇怪的迁移需求!
陈举超
207次阅读
2025-04-15 15:27:53