如何优化mysql Distinct?

时间:2011-07-05 03:43:01

标签: mysql sql

Tbl_responses

  • ID
  • 响应
  • MSGID
  • 用户名

有5,000条记录。 “zac1987”发布了800条回复。 “zac1987”发布的800条回复中有30条差异msgid

SELECT DISTINCT msgid 
  FROM Tbl_responses 
 WHERE username = 'zac1987';

目前Explain SQL显示有800行受影响。如何优化查询,以便只有30行?我认为必须有一个解决方案来避免循环/过滤800条记录...就像用我在博客上显示的JOIN子句问题替换WHERE子句... ye5.blogspot.com/2011/07/optimize-faster-mysql-query-speed.html我正在寻找一些专家来避免循环800条记录的解决方案。

我的另一个问题 - 为什么这个页面http://forge.mysql.com/wiki/Top10SQLPerformanceTips说“当你拥有或可以使用GROUP BY时不要使用DISTINCT”因为它会减慢查询速度?但我已经测试过,结果没有减速,为什么?

4 个答案:

答案 0 :(得分:2)

正如您所说,尝试重写查询以使用GROUP BY子句:

SELECT msgid 
  FROM Tbl_responses 
 WHERE username = 'zac1987' GROUP BY msgid;

看看性能上的差异

答案 1 :(得分:1)

检查覆盖索引是否会在您的情况下表现更好。 http://ronaldbradford.com/blog/tag/covering-index/

答案 2 :(得分:1)

这两个查询是等价的:

SELECT DISTINCT msgid 
FROM Tbl_responses 
WHERE username = 'zac1987' ;

SELECT msgid 
FROM Tbl_responses 
WHERE username = 'zac1987'
GROUP BY msgid ;

我建议你在(username, msgid)上制作复合索引。这将有助于任一版本的查询。

但最好是制作一个包含10K(甚至100k或1M)行的测试表并尝试速度和执行计划,首先使用(username)上的简单索引,然后使用复合索引(username, msgid)

差异将显示在执行计划的Extra列中,对于第一个带有简单索引的案例,它将显示 “使用where,using temporary” ,在第二种情况下,使用复合索引,它将显示 “使用位置,使用索引”

正如都铎指出的那样,担心5000记录的速度是过早的优化。当你有500K记录或者你看到性能下降时,你应该开始担心。


注意:这两个查询是 NOT 等效的,因此您不能总是通过将字段移动到GROUP BY来删除DINSTINT子句并期望得到相同的结果:

SELECT DISTINCT msgid, response
FROM Tbl_responses 
WHERE username = 'zac1987' ;

SELECT msgid, response
FROM Tbl_responses 
WHERE username = 'zac1987'
GROUP BY msgid ;

答案 3 :(得分:0)

放置一些条件,如WHERE username ='zac1987'AND id ='XYZ' 因为根据您的要求,不可能使用distinct和group过滤行。