背景
最近某同事问我一个关于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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【MySQL 30周年庆】MySQL 8.0 OCP考试限时免费!教你免费领考券
墨天轮小教习
2966次阅读
2025-04-25 18:53:11
MySQL 30 周年庆!MySQL 8.4 认证免费考!这次是认真的。。。
严少安
851次阅读
2025-04-25 15:30:58
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
495次阅读
2025-04-17 17:02:24
MySQL 9.3 正式 GA,我却大失所望,新特性亮点与隐忧并存?
JiekeXu
435次阅读
2025-04-15 23:49:58
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
373次阅读
2025-04-15 14:48:05
MySQL 8.0 OCP 1Z0-908 考试解析指南(二)
JiekeXu
290次阅读
2025-04-30 17:37:37
记录MySQL数据库的一些奇怪的迁移需求!
陈举超
278次阅读
2025-04-15 15:27:53
SQL优化 - explain查看SQL执行计划(下)
金同学
273次阅读
2025-05-06 14:40:00
MySQL 8.0 OCP 1Z0-908 考试题解析指南
青年数据库学习互助会
255次阅读
2025-04-30 12:17:54
MySQL 30 周年庆!MySQL 8.4 认证免费考!这次是认真的。。。
数据库运维之道
245次阅读
2025-04-28 11:01:25