2012-02-10 77 views
2

我的工作,在约1.2秒运行在由126000点的记录填充的MyISAM表的简单查询:MySQL的简单,但慢查询(错误索引?)

SELECT * FROM my_table 
WHERE primary_key != 5 AND 
(
    col1 = 528 OR (col2 = 265 AND col3 = 1) 
) 
ORDER BY primary_key DESC 

我已经为建立单一指标where子句中使用的每个字段,但只有primary_key(my_table的自动增量字段)用作关键字,而col1和col2仅被忽略,查询变得更慢。我应该如何创建索引(可能是多索引)或编辑查询?

+0

索引必须与查询(DESC)保持同一方向。 – Alfabravo 2012-02-10 17:10:41

回答

0

使用EXPLAIN找出发生了什么。这将标识正在使用哪些索引,从而使您能够调整查询。

0

不幸的是,几乎没有办法预测哪些索引在没有对MySQL内部的全面理解的情况下会比其他索引更好。但是,对于每个查询(或者至少子查询/连接),MySQL只会使用1个索引,因此您已经声明主键正在使用,所以我假设您已经查看了EXPLAIN输出。

您可能希望尝试使用不同顺序在(primary_key,col1,col2,col3)或其中的一个子集上的多列索引来查找最佳结果。最好的索引将主要取决于列的基数,因此甚至可能随时间而改变,这取决于表中的数据。

4

,如果你有以下的多列“覆盖”指标,您将获得最佳性能:

(primary_key, col1) 
(primary_key, col2, col3) 

,并发出以下查询:

(SELECT * FROM my_table 
WHERE primary_key != 5 AND 
    col1 = 528) 
UNION 
(SELECT * FROM my_table 
WHERE primary_key != 5 AND 
col2 = 265 AND col3 = 1) 
ORDER BY primary_key DESC 

你可能会变化,更好,性能通过改变索引中字段的顺序,基于基数。

在您原来的查询中,WHERE子句中的整个选择都不会使用索引,这会导致部分表扫描。

在上面的查询中,第一个子查询能够完全利用第一个索引,避免任何表扫描,第二个子查询使用第二个索引。

不幸的是,MySQL将无法利用索引对整个结果集上的记录进行排序,并可能使用filesort对它们进行排序。因此,如果您不需要按primary_key排序的记录,请删除外部的ORDER子句以获得更好的性能,但如果结果集较小,则不应该成为问题。