GROUP BY子句中的列顺序确实会影响索引使用

时间:2017-10-27 12:40:05

标签: mysql sql mariadb

这更像是一个学术问题,因为在我的特定情况下,我可以创建一个简单的解决方法,但我想了解这背后的原因。

使用InnoDB表(MariaDB 10.0.31)和(以及其他)客户和uri列,我想为特定客户选择不同的uris。现在,该表非常大(约50M条目),因此客户和uri上有一个综合索引。

基本上我不明白为什么group by子句中列的顺序很重要。

explain select customer, uri from `tableName` group by customer,uri;

告诉我它将使用现有的group by,但是

explain select customer, uri from `tableName` group by uri,customer;

不会这样做。

有人可以解释为什么会这样吗?我一直认为group by子句是声明性的。

也许是因为它是周五,但我想不出一个案例,按列的顺序会影响结果。

3 个答案:

答案 0 :(得分:1)

你的观察是正确的。结果会有所不同,因为复合索引声明中提到的列的“前缀”顺序用于基于成本的优化程序的决策。这种行为是由于使用了B-TREE索引

GROUP BY子句用于排序结果,因此用于

  • 使用了正确的索引顺序或
  • 只有最左边的列才能在
  • 组中使用
  • 最左边的列在WHERE子句中使用,并且在GROUP BY子句中使用正确的顺序将使用索引。

有关松散/紧密索引扫描的更多信息,请点击此处 https://dev.mysql.com/doc/refman/5.7/en/group-by-optimization.html

答案 1 :(得分:0)

在索引中基本上是一个有序的表。在你的情况下,它按照ORDER BY customer, uri的顺序排序(因为这是你的索引的定义方式)。

MySQL执行group by首先根据group by子句对结果进行排序,然后使用相同的值折叠行(在排序后碰巧相互跟随)。

显然,MySQL不够智能,无法识别在以其他方式排序结果时也可以执行不同的group by子句。

更多相关信息:

答案 2 :(得分:0)

在bugs.mysql.com上写一个功能请求。

一方面,GROUP BY被定义为(或被定义)暗示ORDER BY具有相同顺序的相同列。

另一方面,如果您忽略该非标准功能,即使通过说ORDER BY NULL,MySQL也无法对列进行随机播放以使用索引。

5.7 (and before)

  

GROUP BY默认情况下隐式排序(即,在没有ASC的情况下)   或DESC指示符),但依赖于隐式GROUP BY排序   弃用。要生成给定的排序顺序,请使用显式ASC或DESC   GROUP BY列的指示符或提供ORDER BY子句。组   BY排序是MySQL扩展,可能在将来的版本中发生变化;   例如,使优化器可以对分组进行排序   以任何它认为最有效的方式并避免分类   开销。

  

如果查询包含GROUP BY但您想避免开销   对结果进行排序,可以通过指定ORDER BY来抑制排序   NULL。

但请注意; 8.0

  

以前,不推荐使用隐式GROUP BY排序   GROUP BY默认排序(即没有ASC或DESC时)   代号)。在MySQL 8.0中,GROUP BY默认情况下不再排序,所以   查询结果可能与以前的MySQL版本不同。生产一个   给定排序顺序,对GROUP BY使用显式ASC或DESC指示符   列或提供ORDER BY子句。