MySQL:使用DISTINCT优化​​查询

时间:2011-09-03 20:35:59

标签: mysql sql query-optimization distinct

在我的Java应用程序中,我发现了一个小的性能问题,这是由这样简单的查询引起的:

 SELECT DISTINCT a 
   FROM table 
  WHERE checked = 0 
  LIMIT 10000

我在checked列上有索引。

在开始时,查询非常快(即几乎所有行都有checked = 0)。但是当我标记越来越多的行时,查询变得非常低效(最多几分钟)。

如何改善此查询的效果?我应该添加一个复杂的索引

  • a,已选中

或者更确切地说

  • 选中,一个?

我的表有很多行,这就是为什么我不想手动测试它并希望有幸得到猜测。

5 个答案:

答案 0 :(得分:2)

我会在checked, a上添加一个索引。这意味着您已返回的值已在索引中找到,并且无需重新访问该表即可找到它。其次,如果您正在对表格进行大量更新,则表格和索引很可能在光盘上碎片化。重建(压缩)表和索引可以显着提高性能。

您也可以使用重写的查询(以防优化器不理解它是等效的):

  SELECT a 
    FROM table 
   WHERE checked = 0 
GROUP BY a
   LIMIT 10000

答案 1 :(得分:1)

在DISTINCT列上添加复合索引(在本例中为a)。 MySQL能够将此索引用于DISTINCT

MySQL也可以在(a, checked)上获取复合索引(顺序重要,DISTINCT列必须位于索引的开头)。尝试两者并将结果与​​您的数据和查询进行比较。

(添加此索引后,您应在Using index for group-by输出中看到EXPLAIN。)

请参阅手册中的 GROUP BY optimization 。 (DISTINCTGROUP BY非常相似。)

  

处理GROUP BY的最有效方法是使用索引直接检索分组列。使用此访问方法,MySQL使用某些索引类型的属性(按键排序)(例如,BTREE)。此属性允许在索引中使用查找组,而无需考虑索引中满足所有WHERE条件的所有键。>

答案 2 :(得分:1)

  

我的桌子上有数百万行< ...>几乎所有行都有   检查= 0

在这种情况下,似乎最好的索引是简单的(a)

<强>更新

目前尚不清楚要检查多少行。从你的评论旁边的问题:

  

在开头0是100%的行,但在一天结束时它会   变为0%

这会改变一切。所以@Ben有正确的答案。

答案 3 :(得分:0)

我找到了一个完全不同的解决方案,可以解决问题。我将简单地创建一个包含所有可能的唯一“a”值的新表。这将允许我避免DISTINCT

答案 4 :(得分:0)

您没有说明,但是您是否定期更新索引?随着基础数据的变化,索引变得越来越不准确,处理越来越差。如果您有一个已选中的索引,并且正在更新已检查的索引,则需要确保定期更新索引。