mysql - SQL `group by` 与 `order by` 性能

标签 mysql sql postgresql group-by sql-order-by

tl;dr - 许多已接受的 stackoverflow 答案建议使用子查询来影响 GROUP BY 子句返回的行。虽然这可行,但这是最好的建议吗?


我知道已经有很多关于如何在 GROUP BY 语句中检索特定行的问题。它们中的大多数都围绕着在 FROM 子句中使用子查询。子查询将适本地对表进行排序,并且将针对现在排序的临时表运行分组依据。一些例子,

PostgreSQL 不再需要使用 distinct on() 子句进行子查询。

但是,在任何这些情况下,我都不明白的是,我试图做一些系统最初可能没有设计的事情时,我是在搬起石头砸自己的脚。下面以 PostgreSQL 和 MySQL 中的两个例子为例,

在这两种情况下,我都有一个帖子表,其中包含同一帖子的多个版本(由其 UUID 表示)。我想选择每个帖子的最近 published 版本,按它的 created_at 字段排序。

我最担心的是,鉴于 MySQL 方法,临时表是必要的。将其提升到“网络规模”(lolz),我想知道我是否处于受伤的世界。我是否应该重新考虑我的模式,或者是否有足够的方法优化子查询-父查询关系以使其正常?

最佳答案

绝对不是最好的建议。 SQL 本身(以及据我所知的 MySQL 文档)几乎没有说明带有 order by 的子查询的结果。虽然它们可能在实践中被订购,但不能保证它们是。

更重要的问题是在聚合中使用“隐藏列”。考虑这个基本查询:

select t.*
from (select t.* from table t order by datecol) t
group by t.col;

select 中除 t.col 之外的所有内容都来自 indeterminate 行。具体documentation是(重点是我的):

MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values within each group the server chooses.

编写此类查询的安全方法是:

select t.*
from table t
where not exists (select 1
                  from table t2
                  where t2.col = t.col and t2.datecol < t.datecol
                 );

这并不完全相同,因为如果最小值不唯一,它将返回多个值。逻辑是“获取表中所有行,其中没有行具有相同的 col 值和较小的 datecol 值。

编辑:

您评论中的问题没有意义,因为没有讨论两个查询。在 MySQL 中,您可以使用带有变量的 order by 来解决这个问题:

select t.*
from (select t.*,
             @rn := if(@col = col, @rn := @rn + 1, 1) as rn,
             @col := col
      from table t cross join
           (select @col := '', @rn := 0) vars
      order by col, datecol) t
where rn = 1;

这个方法应该比 order bygroup by 更快。​​

关于mysql - SQL `group by` 与 `order by` 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23785194/

相关文章:

sql - 有人能解释一下 union All 和 join in oracle SQL 有什么区别吗

sql - 从一个表中选择匹配另一个条件的表?

python - 如何从 Pandas 数据框创建 postgres 表?

mysql - 首选项和用户特定设置

mysql - 无法创建此 MySQL UDF

c++ - 为什么使用 PHP 数百个数据库连接无关紧要..但在 C++ 应用程序中却很重要?

sql - 在 postgres 的数组列上使用 regexp_replace

postgresql - 多边形搜索中的点太慢

postgresql - 这个 "psql (9.4.8, server 9.3.23)"是什么意思?

mysql连接两张表,得到匹配记录中非零值的字段名