mysql8.0 优化器干的坏事儿

构建测试数据

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;

得到结果
3.png

-------以上结果 在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

9.png

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)

即然8.0优化器要改写我们的语句,我们就不让它改。
改动很简单

select * from 
(
select(@i1:= @i1 + 1) as sort_i, sname,score from test_1 ,(select   @i1:= 0) t1 
limit 100
) t2 where score >60

结果也变正确了。


3.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 很多公司对于 MySQL5.7 升级到 MySQL8.0 都会顾虑应用是否会受到影响,其实这个主要看8.0相比5....
    轻松的鱼阅读 8,605评论 0 2
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 11,278评论 0 4
  • 公元:2019年11月28日19时42分农历:二零一九年 十一月 初三日 戌时干支:己亥乙亥己巳甲戌当月节气:立冬...
    石放阅读 11,804评论 0 2