背景
最近某同事问我一个关于group by 后需要返回每个分类最新/最老的创建时间的数据,随后我想了想...叮,还好记得以前有遇到过这样的疑问,就给他说使用子查询就好了。。如果事情这么简单。。就没有这篇东西了。
分析
原来的语句
select * from tb_test where tt_id = 9000 GROUP BY tt_id order by create_time desc;复制
我们改了之后还有问题的语句
select * from (select * from tb_test where tt_id = 9000 order by create_time desc) as sub GROUP BY tt_id;复制
上面条语句还是不能进行排序后分组的
于是想起来应该还是要加些什么东西的,搜索了以前的记录发现有关于5.7的 derived_merge(派生合并) 优化
可以通过下面几个关键字阻止合并操作
DISTINCT
GROUP BY
HAVING
LIMIT复制
于是就有了
select * from (select * from tb_test where tt_id = 9000 having 1=1 order by create_time desc) as sub GROUP BY tt_id;复制
就是增加一个 having
关键字,当然你的语句如果正好有其他关键字那么是不用再增加了,我们原来打算增加limit但是这感觉太挫了。。。
有一个方法可以看到是否进行了
执行 explain,可以看到下面的话就没有进行derived_merge ,否则就是执行了
2 DERIVED tb_test ALL 49 10.00 Using where; Using filesort复制
derived_merge 拓展
derived_merge 是5.7版本做的一个优化吧,所以去除派生类与外部块合并,是可以减少查询开销,派生类是个临时表,开辟一个临时表的同时还要维护和排序或者分组,都会影响效率。
多种办法不需要修改 derived_merge 参数而使合并派生类失效,原文如下
可以通过在子查询中使用任何阻止合并的构造来禁用合并,尽管这些构造对实现的影响并不明确。防止合并的构造对于派生表和视图引用是相同的:1.聚合函数( SUM() , MIN() , MAX() , COUNT()等)2.DISTINCT3.GROUP BY4.HAVING5.LIMIT6.UNION或UNION ALL7.选择列表中的子查询8.分配给用户变量9.仅引用文字值(在这种情况下,没有基础表)
因为mysql 这个优化会导致我们的子查询语句会合并在一起和外部语句进行查询。
文章转载自炉门点饭,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【专家有话说第五期】在不同年龄段,DBA应该怎样规划自己的职业发展?
墨天轮编辑部
1295次阅读
2025-03-13 11:40:53
MySQL8.0统计信息总结
闫建(Rock Yan)
484次阅读
2025-03-17 16:04:03
2月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
456次阅读
2025-03-13 14:38:19
Ogg23ai高手必看-MySQL Innodb Cluster跟oracle的亲密接触
曹海峰
453次阅读
2025-03-04 21:56:13
SQL优化 - explain查看SQL执行计划(一)
金同学
388次阅读
2025-03-13 16:04:22
MySQL突然崩溃?教你用gdb解剖core文件,快速锁定“元凶”!
szrsu
349次阅读
2025-03-13 00:29:43
MySQL生产实战优化(利用Index skip scan优化性能提升257倍)
chengang
327次阅读
2025-03-17 10:36:40
MySQL数据库当前和历史事务分析
听见风的声音
260次阅读
2025-04-01 08:47:17
一键装库脚本3分钟极速部署,传统耗时砍掉95%!
IT邦德
237次阅读
2025-03-10 07:58:44
MySQL8.0直方图功能简介
Rock Yan
228次阅读
2025-03-21 15:30:53