在我的Java应用程序中,我发现了一个小的性能问题,这是由这样简单的查询引起的:
SELECT DISTINCT a
FROM table
WHERE checked = 0
LIMIT 10000
我在checked
列上有索引。
在开始时,查询非常快(即几乎所有行都有checked
= 0)。但是当我标记越来越多的行时,查询变得非常低效(最多几分钟)。
如何改善此查询的效果?我应该添加一个复杂的索引
或者更确切地说
我的表有很多行,这就是为什么我不想手动测试它并希望有幸得到猜测。
答案 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 。 (DISTINCT
与GROUP BY
非常相似。)
处理GROUP BY的最有效方法是使用索引直接检索分组列。使用此访问方法,MySQL使用某些索引类型的属性(按键排序)(例如,BTREE)。此属性允许在索引中使用查找组,而无需考虑索引中满足所有WHERE条件的所有键。>
答案 2 :(得分:1)
我的桌子上有数百万行< ...>几乎所有行都有 检查= 0
在这种情况下,似乎最好的索引是简单的(a)
。
<强>更新强>
目前尚不清楚要检查多少行。从你的评论旁边的问题:
在开头0是100%的行,但在一天结束时它会 变为0%
这会改变一切。所以@Ben有正确的答案。
答案 3 :(得分:0)
我找到了一个完全不同的解决方案,可以解决问题。我将简单地创建一个包含所有可能的唯一“a”值的新表。这将允许我避免DISTINCT
答案 4 :(得分:0)
您没有说明,但是您是否定期更新索引?随着基础数据的变化,索引变得越来越不准确,处理越来越差。如果您有一个已选中的索引,并且正在更新已检查的索引,则需要确保定期更新索引。