什么更快,MySQL中的SELECT DISTINCT或GROUP BY?

时间:2009-02-24 12:04:19

标签: mysql sql database group-by distinct

如果我有桌子

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

15 个答案:

答案 0 :(得分:234)

它们本质上是相互对应的(实际上这是一些数据库在引擎盖下实现DISTINCT的方式)。

如果其中一个更快,那将是DISTINCT。这是因为,虽然两者是相同的,但查询优化器必须注意到GROUP BY没有利用任何组成员,只有他们的密钥的事实。 DISTINCT明确表示这一点,因此您可以使用略微笨拙的优化器。

如有疑问,请测试!

答案 1 :(得分:98)

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

如果不这样做,请使用DISTINCT

GROUP BY中的

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

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

并按DESC顺序排列您的专业。

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

所以

SELECT DISTINCT u.profession FROM users u
如果您在profession上没有索引,

会更快。

答案 2 :(得分:17)

如果可以的话,选择最简单和最短的方式 - DISTINCT似乎更符合您的要求,因为它只会为您提供所需的答案而且只有这一点!

答案 3 :(得分:15)

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

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

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

答案 4 :(得分:7)

在某些情况下,在postgres中(不知道其他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

所以要小心......:)

答案 5 :(得分:7)

Group by比Distinct贵,因为Group by对结果进行了排序,同时避免了它。但是,如果你想通过产生相同的结果而得到与 按黄色相同的结果 ..

SELECT DISTINCT u.profession FROM users u

等于

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

答案 6 :(得分:5)

似乎查询不完全相同。至少对于MySQL。

比较

  1. 描述从northwind.products中选择不同的productname
  2. 描述来自northwind.products group by productname
  3. 的select productname

    第二个查询在Extra。

    中另外提供了“Using filesort”

答案 7 :(得分:3)

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

答案 8 :(得分:2)

(更多功能性说明)

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

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

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

答案 9 :(得分:2)

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

答案 10 :(得分:1)

如果您不需要执行任何组功能(总和,平均值等,以防您想要向表中添加数值数据),请使用SELECT DISTINCT。我怀疑它更快,但我没有什么可以表现出来的。

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

答案 11 :(得分:1)

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

SELECT sql_no_cache opnamegroep_intern   来自telwerken   在opnemergroep IN(7,8,9,10,11,12,13)组由opnamegroep_intern

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

SELECT sql_no_cache distinct(opnamegroep_intern)   来自telwerken   在opnemergroep IN(7,8,9,10,11,12,13)

635 totaal 0.2117秒(差不多100%) Weergave van记录0 - 29(635 totaal,query duurde 0.3468 sec)

答案 12 :(得分:1)

这不是规则

对于每个查询....尝试单独区分然后分组...比较完成每个查询的时间并使用更快....

在我的项目中,有时候我会使用group by和其他不同的

答案 13 :(得分:0)

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

答案 14 :(得分:0)

如果问题允许,请尝试使用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 )

这并非总是可行,但如果可用,您会看到更快的响应。