在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

?

237569 次浏览

它们本质上是等价的(实际上这就是一些数据库在底层实现DISTINCT的方式)。

如果其中一个更快,它将是DISTINCT。这是因为,尽管两者是相同的,但查询优化器必须捕捉到这样一个事实:你的GROUP BY没有利用任何组成员,只是利用了他们的键。DISTINCT明确了这一点,所以你可以使用一个稍微笨一点的优化器。

有疑问的时候,测试一下!

如果你不需要执行任何组函数(如果你想将数值数据添加到表中,可以使用sum, average等),请使用SELECT DISTINCT。我怀疑它更快,但我没有任何表现。

在任何情况下,如果您担心速度,可以在列上创建索引。

似乎这些查询并不完全相同。至少对MySQL是这样。

比较:

  1. 描述从northwind.products中选择不同的产品名称
  2. 描述从北风选择的产品名称。产品组按产品名称

第二个查询在Extra中额外给出了“Using filesort”。

如果可以,尽量选择最简单、最简短的答案——DISTINCT似乎更符合你的要求,因为它会给你你需要的答案,而且只有这个答案!

如果你在profession上有一个索引,这两个是同义词。

如果没有,则使用DISTINCT

MySQL中的GROUP BY对结果进行排序。你甚至可以这样做:

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

并把你的职业按DESC的顺序排序。

DISTINCT创建一个临时表并使用它来存储副本。GROUP BY做同样的事情,但随后对不同的结果进行排序。

所以

SELECT DISTINCT u.profession FROM users u

是更快的,如果你在profession上没有索引。

SELECT DISTINCT总是和GROUP BY一样,或者比GROUP BY更快。在某些系统上(例如Oracle),对于大多数查询,它可能被优化为与DISTINCT相同。在其他的(如SQL Server)上,它可能要快得多。

在postgres的某些情况下,distinct可能比group by慢(不知道其他dbs)。

测试的例子:

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

所以要小心……:)

(更多的是功能性说明)

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

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

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

以上所有答案都是正确的,对于单列上的DISTINCT和单列上的GROUP BY的情况。 每个db引擎都有自己的实现和优化,如果你只关心一点点差异(在大多数情况下),那么你必须针对特定的服务器和特定的版本进行测试!

但是,如果在查询中选择多个列,则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是这种方式的通用关键字。

所以朋友们,你们要小心,不要把上面的答案当成所有情况下的正确答案……你可能会感到困惑,得到错误的结果,而你想要的只是优化!

Group by比Distinct代价更大,因为Group by对结果进行排序,而Distinct则避免排序。但如果你想让group by产生与distinct相同的结果,则给出order by null ..

SELECT DISTINCT u.profession FROM users u

等于

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

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

如果问题允许它,尝试EXISTS,因为它被优化为一找到结果就结束(并且不缓冲任何响应),所以,如果你只是试图为这样的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 )

这并不总是可行的,但当可用时,你会看到一个更快的响应。

经过大量的测试,我们得出的结论是GROUP BY更快

< p >选择sql_no_cache opnamegroep_intern 从telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13) group by opnamegroep_intern

635总共0.0944秒 Weergave van记录0 - 29(总共635,查询duurde 0.0484秒)

< p >选择sql_no_cache 不同的(opnamegroep_intern) 从telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13)

635总共0.2117秒(几乎100%慢) Weergave van记录0 - 29(总共635,查询duurde 0.3468秒)

这不是规则

对于每个查询....试着分开,然后按…分组比较完成每个查询的时间,并使用更快的....

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

下面是一个简单的方法,它将为每个查询打印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;

它简单地显示了解析、编译和执行每条语句所需的毫秒数,如下所示:

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

在mySQL中,我发现GROUP BY将NULL视为不同的,而distinct不是。
采取完全相同的DISTINCT查询,删除了DISTINCT,并将所选字段添加为GROUP BY,并且由于其中一个字段为NULL,我得到了更多的行

所以. .我倾向于相信mySQL中有更多的DISTINCT。