DISTINCT和GROUP BY之间的性能差异

时间:2012-11-13 01:09:01

标签: mysql performance group-by distinct

我的理解是,在(My)SQL中,SELECT DISTINCT应该对所有列的GROUP BY做同样的事情,除了GROUP BY进行隐式排序,所以这两个查询应该是一样的:

SELECT boardID,threadID FROM posts GROUP BY boardID,threadID ORDER BY NULL LIMIT 100;
SELECT DISTINCT boardID,threadID FROM posts LIMIT 100;

他们都给了我相同的结果,他们从EXPLAIN得到相同的输出:

+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra           |
+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
|  1 | SIMPLE      | posts | ALL  | NULL          | NULL | NULL    | NULL | 1263320 | Using temporary |
+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
1 row in set

但在我的桌面上,DISTINCT的查询会立即返回,GROUP BY的查询大约需要4秒。我已禁用查询缓存来测试它。

有25列,所以我也尝试创建一个单独的表,其中只包含 boardID和threadID列,但同样的问题和性能差异仍然存在。

使用GROUP BY代替DISTINCT,因此我可以添加其他列,而不会将它们包含在DISTINCT的评估中。所以现在我不知道如何继续。为什么会有区别?

1 个答案:

答案 0 :(得分:3)

首先,您的查询不完全相同 - GROUP BY具有ORDER BY,但DISTINCT没有。

请注意,在任何一种情况下,都不使用索引,这对性能不利。

我建议为(boardid, threadid)创建复合索引 - 这应该让两个查询都能使用索引,并且两者都应该开始更快地工作

编辑:解释为什么SELECT DISTINCT ... LIMIT 100在没有索引时比GROUP BY ... LIMIT 100快。

要执行第一个语句(SELECT DISTINCT),服务器只需要获取100个,可能稍微多一行,并且只要它有100个不同的行就可以停止 - 没有更多的工作要做。 这是因为原始SQL语句没有指定任何顺序,因此服务器可以随意提供任意100行,只要它们是不同的。但是,如果您要在ORDER BY之前对此进行任何无索引LIMIT 100,则此查询将立即变慢。

要执行第二个语句(SELECT ... GROUP BY ... LIMIT 100),MySQL始终使用GROUP BY中使用的相同列进行隐式ORDER BY。换句话说,它在获取前几个100多行之后不能快速停止,直到获取,分组和排序所有记录。在那之后,它会应用你添加的ORDER BY NULL(我猜这不会做太多,但放弃它可能会加快速度),最后,它会获得前100行并抛弃剩余的结果。当然,这很慢。

当你有复合索引时,在任何一种情况下都可以非常快速地完成所有这些步骤。