在MySQL中SELECT DISTINCT或GROUP BY更快吗?

如果我有一张桌子

CREATE TABLE users ( id int(10) unsigned NOT NULL auto_increment, name varchar(255) NOT NULL, profession varchar(255) NOT NULL, employer varchar(255) NOT NULL, PRIMARY KEY (id) ) 

我想获得profession领域的所有独特价值,什么会更快(或推荐):

 SELECT DISTINCT u.profession FROM users u 

要么

 SELECT u.profession FROM users u GROUP BY u.profession 

它们本质上是相同的(事实上,这是一些数据库如何在DISTINCT实现DISTINCT )。

如果其中一个更快,这将是DISTINCT 。 这是因为,虽然两者是相同的,但是查询优化器必须知道你的GROUP BY没有利用任何组成员,只是他们的关键。 DISTINCT使得这个明确,所以你可以离开稍微优化的优化器。

如有疑问,testing!

如果你有一个profession的指数,这两个是同义词。

如果你不这样做,那么使用DISTINCT

MySQL GROUP BY对结果进行sorting。 你甚至可以这样做:

 SELECT u.profession FROM users u GROUP BY u.profession DESC 

并按照DESC顺序sorting你的职业。

DISTINCT创build一个临时表并使用它来存储重复项。 GROUP BY也是这样做的,但是之后对不同的结果进行sorting。

所以

 SELECT DISTINCT u.profession FROM users u 

如果你没有profession的指数,速度会更快。

去尽可能最简单和最短的 – DISTINCT似乎更多的是你要找的只是因为它会给你正确的答案,你需要的只有这一点!

上面的所有答案都是正确的,对于单列上的DISTINCT与单列上的GROUP BY的情况。 每个数据库引擎都有自己的实现和优化,如果你关心的是很less的差别(在大多数情况下),那么你必须testing特定的服务器和特定的版本! 由于实现可能会改变…

但是,如果您在查询中select多个列,那么DISTINCT本质上是不同的! 因为在这种情况下,它将比较所有行的所有列,而不是仅一列。

所以如果你有这样的东西:

 // This will NOT return unique by [id], but unique by (id,name) SELECT DISTINCT id, name FROM some_query_with_joins // This will select unique by [id]. SELECT id, name FROM some_query_with_joins GROUP BY id 

认为DISTINCT关键字通过您指定的第一列来区分行是常见的错误,但DISTINCT是这种方式的一般关键字。

所以,你必须小心,不要把上面的答案作为正确的所有情况…你可能会感到困惑,并得到错误的结果,而你想要的只是优化!

在postgres的某些场合(不了解其他dbs),可能会比group更慢。

testing的例子:

 postgres=# select count(*) from (select distinct i from g) a; count 10001 (1 row) Time: 1563,109 ms postgres=# select count(*) from (select i from g group by i) a; count 10001 (1 row) Time: 594,481 ms 

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

所以要小心… 🙂

似乎查询不完全一样。 至less对于MySQL来说。

比较:

  1. 描述从northwind.products中select不同的产品名称
  2. 用产品名称描述northwind.products组中的产品名称

第二个查询在Extra中额外提供了“使用filesort”。

分组比由于分组不同而不同,并且明显地避免了分组。 但是,如果你想通过产生不同的结果作为不同的秩序由null ..

 SELECT DISTINCT u.profession FROM users u 

等于

 SELECT u.profession FROM users u GROUP BY u.profession order by null 

(更多function说明)

有些情况下,你必须使用GROUP BY,例如,如果你想获得每个雇主的雇员数量:

 SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer 

在这种情况下, DISTINCT u.employer无法正常工作。 也许有办法,但我不知道。 (如果有人知道如何使用DISTINCT进行查询,请添加注释!)

MySQL中 ,“ Group By ”使用额外的步骤: filesort 。 我意识到DISTINCTGROUP BY快,这是一个惊喜。

经过严格的testing,我们得出GROUP BY更快的结论

SELECT sql_no_cache opnamegroep_intern FROM telwerken WHERE opnemergroep IN(7,8,9,10,11,12,13)group by opnamegroep_intern

635共计0.0944秒Weergave面包车logging0 – 29(635 totaal,查询duurde 0.0484秒)

SELECT sql_no_cache distinct(opnamegroep_intern)FROM telwerken WHERE opnemergroep IN(7,8,9,10,11,12,13)

635共0.2117秒(几乎100%慢)Weergave面包车logging0 – 29(635头,询问duurde 0.3468秒)

这不是一个规则

对于每个查询….尝试单独不同然后分组…比较时间来完成每个查询和使用更快….

在我的项目中,有时我会使用group和other

这是一个简单的方法,将打印每个查询的2个不同的时间。

 DECLARE @t1 DATETIME; DECLARE @t2 DATETIME; SET @t1 = GETDATE(); SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT SET @t2 = GETDATE(); PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar); SET @t1 = GETDATE(); SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY SET @t2 = GETDATE(); PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar); 

或者尝试SET STATISTICS TIME(Transact-SQL)

 SET STATISTICS TIME ON; SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY SET STATISTICS TIME OFF; 

它只显示parsing,编译和执行每个语句所需的毫秒数,如下所示:

  SQL Server Execution Times: CPU time = 0 ms, elapsed time = 2 ms. 

如果您不需要执行任何组函数(总和,平均值等等,以防将数字数据添加到表中),请使用SELECT DISTINCT。 我怀疑它更快,但我没有什么可以显示的。

无论如何,如果您担心速度,请在列上创build一个索引。

SELECT DISTINCT将始终与GROUP BY相同或更快。 在某些系统(如Oracle)上,对于大多数查询,它可能被优化为与DISTINCT相同。 在其他人(如SQL Server)上,速度可能会更快。

如果问题允许,请尝试使用EXISTS,因为它已经过优化,一旦find结果就立即结束(并且不要缓冲任何响应),所以,如果您只是想为这样的WHERE子句规范化数据

 SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality 

更快的反应是:

 SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID ) 

这并不总是可能的,但是如果可用,您将看到更快的响应。