为什么MySQL不使用索引?
我们的MySQL(的Percona Server)的数据库中有一个大桌子cotains 1000万行,有很多慢速查询longger超过40秒这样的:为什么MySQL不使用索引?
SELECT col1, Seller, col3, col4, Id, col5
FROM table1
WHERE Seller = 346761
AND col1 IN (2, 3, 4)
AND col3 = 1
AND col4 NOT IN (5,6,7)
ORDER BY Id DESC
LIMIT 0, 20;
我对Seller
创建索引,col1
,col3
,col4
。这些指标是单独的,而不是多列指数(AKA覆盖指数)。 Id
是主键。
EXPLAIN显示MySQL使用主键作为索引来查询这个sql,而不是关于Seller的索引。
+----+-------------+------------------+-------+--------------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+-------+--------------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | trans_audit_list | index | Seller,AuditStatus | PRIMARY | 8 | NULL | 1483 | Using where |
+----+-------------+------------------+-------+--------------------+---------+---------+------+------+-------------+
当我force index (Seller)
,它是非常快,0.7秒。
而我发现如果不使用限制语句,这个查询将使用Seller
索引,会非常快。 为什么MySQL不使用带限制语句的Seller
上的索引?
将多个可能的索引情况添加到ORDER BY DESC
+ LIMIT
条款is a common problematic situation for mysql的优化程序以及强制索引时非常小的情况之一实际上可能是合法的。
请注意,您的子句IN (...)
是优化程序的额外麻烦。
如果你不是真的需要它,我建议按ID ASC
而不是DESC
来订购,这样引擎可以使用主键排序的好处,这是ASC
,直到进一步实施。
正如你所遇到的,有一个索引并不意味着它会被使用。这适用于每个数据库 - 索引选择取决于查询优化器。正如你试过的,强制索引并不意味着你会得到最快的结果。
之后,查询缓存可能没有帮助你 - 查询计划可能被缓存,因此甚至不考虑索引。
MySQL只对每个语句使用一个索引,因此覆盖索引(多列)将是一个好主意,但您必须对其进行测试才能确定。
您的[Seller]上的非群集索引可能具有太多碎片,并且您的统计信息可能已过时,那么查询优化程序可能不会选择最佳查询计划。检查碎片,更新统计信息或在Seller上重新构建非集群索引,当然,如果您也可以为此查询创建覆盖索引,如果此查询经常由用户使用,并且它值得花费。当您创建覆盖索引时,请确保订单是最终用户最常使用的。与您的查询一样,覆盖索引应该位于[seller-> col1-> col3-> col4]
您应该在查询上运行EXPLAIN并发布结果。 – 2013-03-18 03:09:37
**您需要向我们展示表和索引定义。**诊断慢查询需要全表和索引定义,而不仅仅是描述或释义。也许你的表格定义不好。也许索引没有正确创建。也许你没有一个你认为你做过的那个专栏的索引。没有看到表和索引定义,我们不能说。如果你知道如何做一个'EXPLAIN'或者得到一个执行计划,那就把结果也放在问题中。 – 2013-03-18 03:13:23
谢谢,我有我的问题发布EXPLAIN结果。 – KeepZero 2013-03-18 03:20:06