暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MYSQL5.7特性之GROUP BY 排序

炉门点饭 2021-05-13
850

背景

最近某同事问我一个关于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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论