我正在处理一个简单的查询,该查询在由126,000条记录填充的myisam表中运行大约1.2秒:
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 :(得分: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
子句以获得更好的性能,但如果结果集很小,则不应该成为问题。
答案 1 :(得分:0)
使用EXPLAIN了解发生了什么。这将识别正在使用的索引,从而使您能够调整查询。
答案 2 :(得分:0)
不幸的是,如果没有对MySQL内部的全面了解,几乎没有办法预测哪些索引比其他索引更好。但是,对于每个查询(或者,至少是子查询/连接),MySQL将只使用1个索引,您已声明主键正在使用,因此我假设您已查看EXPLAIN输出。
您可能希望以不同的顺序尝试所有(primary_key,col1,col2,col3)或其中一部分的多列索引,以找到最佳结果。最佳索引将主要取决于列的基数,因此,甚至可能会根据表中的数据随时间变化。