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

vav*_*ava 269 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)
)
Run Code Online (Sandbox Code Playgroud)

我希望获得所有独特的profession字段值,更快(或推荐):

SELECT DISTINCT u.profession FROM users u
Run Code Online (Sandbox Code Playgroud)

要么

SELECT u.profession FROM users u GROUP BY u.profession
Run Code Online (Sandbox Code Playgroud)

Squ*_*Cog 248

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

如果其中一个更快,它就会变得更快DISTINCT.这是因为,虽然两者是相同的,但查询优化器必须抓住这样一个事实:你GROUP BY没有利用任何组成员,只有他们的密钥.DISTINCT使这个显而易见,所以你可以使用稍微笨拙的优化器.

如有疑问,请测试!

  • 只有当你没有索引时,DISTINCT才会更快(因为它没有排序).当你有一个索引并且它被使用时,它们就是同义词. (74认同)
  • "DISTINCT"和"GROUP BY"的定义不同,"DISTINCT"不必对输出进行排序,默认情况下为"GROUP BY".然而,在MySQL中,即使是'DISTINCT` +`ORDER BY`也可能_still_比'GROUP BY'更快,因为SquareCog解释了优化器的额外提示. (9认同)
  • 我对此进行了测试,发现在索引列上,mysql,group by比使用相当复杂的查询要快6倍.只需将其添加为数据点.大约100k行.所以测试它并亲眼看看. (5认同)

Qua*_*noi 98

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

如果你不这样做,那就用吧DISTINCT.

GROUP BYMySQL各种结果.你甚至可以这样做:

SELECT u.profession FROM users u GROUP BY u.profession DESC
Run Code Online (Sandbox Code Playgroud)

让你的职业按DESC顺序排序.

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

所以

SELECT DISTINCT u.profession FROM users u
Run Code Online (Sandbox Code Playgroud)

如果您没有索引,则更快profession.

  • 您可以将`ORDER BY NULL`添加到`GROUP BY`以避免排序. (5认同)

小智 17

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


dan*_*ndi 16

上面的所有答案都是正确的,对于单列上的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
Run Code Online (Sandbox Code Playgroud)

认为DISTINCT关键字按行指定的第一列来区分行是一个常见的错误,但DISTINCT是这种方式的通用关键字.

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

  • 虽然这个问题*是关于MySQL的*,但应该注意第二个查询在MySQL中只能**.几乎所有其他DBMS都会拒绝第二个语句,因为它是GROUP BY运算符的无效使用. (3认同)
  • Postgres,Oracle,Firebird,DB2,SQL Server入门。MySQL:http://sqlfiddle.com/#!2 / 6897c / 1 Postgres:http://sqlfiddle.com/#!12 / 6897c / 1 Oracle:http://sqlfiddle.com/#!12 / 6897c / 1个SQL Server:http://sqlfiddle.com/#!6 / 6897c / 1 (3认同)

小智 7

在某些情况下,在明亮的情况下,明显不同于组(不了解其他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
Run Code Online (Sandbox Code Playgroud)

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

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


Ran*_*ith 7

Group by比Distinct贵,因为Group by对结果进行排序而明显避免它.但是如果你想通过yield得到与group相同的结果,则按null命令.

SELECT DISTINCT u.profession FROM users u
Run Code Online (Sandbox Code Playgroud)

等于

SELECT u.profession FROM users u GROUP BY u.profession order by null
Run Code Online (Sandbox Code Playgroud)


小智 6

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


ama*_*nov 5

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

相比:

  1. 描述从northwind.products中选择不同的productname
  2. 使用productname描述从northwind.products group中选择productname

第二个查询在Extra中另外提供了"Using filesort".

  • 他们在得到什么方面是相同的,而不是在如何得到它方面是相同的。理想的优化器会以相同的方式执行它们,但 MySQL 优化器并不理想。根据你的证据,DISTINCT 似乎会更快——O(n) vs O(n*log n)。 (2认同)