mysql derived_merge_group by排序,derived_merge优化的坑

一个简单的表

CREATE TABLE `test` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`spu_id` int(11) DEFAULT NULL,

`price` decimal(10,2) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

大概内容

| id | spu_id | price |

| —- | —— | —– |

| 1 | 100 | 200 |

| 2 | 100 | 100 |

| 3 | 200 | 400 |

| 4 | 200 | 200 |

对spu_id进行分组,按price从小到大排序:

SELECT * FROM `test` GROUP BY spu_id ORDER BY price

直接使用group by 查出来的数据是按id顺序分组的,并未达到预期

1. 尝试使用子查询,先排序再分组

SELECT

*

FROM

( SELECT * FROM `test` ORDER BY price ) AS tmp

GROUP BY spu_id

注意:这个方式在低版本中有效。在5.7版本中引入新特性 derived_merge优化过后无效了。

具体无效原因我们可使用explain 分析

EXPLAIN

SELECT

*

FROM

( SELECT * FROM `test` ORDER BY price) AS tmp

GROUP BY spu_id;

如图所示:

a9017340d92e7284e4155069257386f0.png

MySQL 将子查询优化成了一个简单查询,子查询中的排序无效~

解决方法:

1. 将derived_merge 关闭

SET optimizer_switch='derived_merge=off';

SET GLOBAL optimizer_switch='derived_merge=off';

2. 使用特殊的查询阻止 derived_merge 优化

可以通过在子查询中使用任何阻止合并的构造来禁用合并,尽管这些构造对实现的影响不那么明显。防止合并的构造与派生表和视图引用相同:

DISTINCT

GROUP BY

HAVING

LIMIT

选择列表中的子查询

分配给用户变量

仅引用文字值(在这种情况下,没有基础表)

以上内容参考文档:mysql文档

那么我们可以将上面的那条sql语句修改为:

SELECT

*

FROM

( SELECT * FROM `test` HAVING 1=1 ORDER BY price ) AS tmp

GROUP BY spu_id;

使用 having 来阻止合并

那么再用explain看看

a79fe70f176f676385b04dfe0ea45415.png

如有错误请指正~ 请多包涵

本作品采用《CC 协议》,转载必须注明作者和本文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值