2

我的理解是,在(My)SQL 中,a应该在所有列上SELECT DISTINCT做与 a 相同的事情,除了隐式排序,所以这两个查询应该是相同的:GROUP BYGROUP 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. 所以现在我不知道如何进行。为什么有区别?

4

1 回答 1

3

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

请注意,在任何一种情况下,都不会使用索引,这对性能没有好处。

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

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

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

要执行第二条语句 ( SELECT ... GROUP BY ... LIMIT 100),MySQL 总是隐含ORDER BY在 GROUP BY 中使用的相同列。换句话说,它不能在获取前 100+ 行之后快速停止,直到所有记录都被获取、分组和排序。之后,它会应用ORDER BY NULL您添加的内容(我猜这并没有多大作用,但删除它可能会加快速度),最后,它会获得前 100 行并丢弃剩余的结果。当然,这该死的慢。

当您拥有复合索引时,无论哪种情况,所有这些步骤都可以非常快速地完成。

于 2012-11-13T05:11:18.563 回答