为啥 MySQL 不使用索引?
Posted
技术标签:
【中文标题】为啥 MySQL 不使用索引?【英文标题】:Why Does MySQL not use an index?为什么 MySQL 不使用索引? 【发布时间】:2013-03-18 02:54:35 【问题描述】:我们的 mysql(Percona Server) 数据库有一个包含 1000 万行的大表,有很多长于 40 秒的慢查询:
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,而不是关于卖方的索引。
+----+-------------+------------------+-------+--------------------+---------+---------+------+------+-------------+
| 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秒。
我发现如果不使用limit语句,这个查询会使用Seller
索引,会非常快。
为什么 MySQL 不使用带有限制语句的 Seller
上的索引?
【问题讨论】:
您应该对查询运行 EXPLAIN 并发布结果。 您需要向我们展示表和索引定义。 诊断慢查询需要完整的表和索引定义,而不仅仅是描述或解释。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。如果您知道如何处理EXPLAIN
或获取执行计划,请将结果也放入问题中。
谢谢,我已经在我的问题中发布了 EXPLAIN 结果。
【参考方案1】:
在ORDER BY DESC
+ LIMIT
子句is a common problematic situation for mysql 的优化器中添加了多个可能的索引情况,并且强制索引实际上是合法的极少数情况之一。
另请注意,您的子句 IN (...)
给优化器带来了额外的麻烦。
如果您真的不需要它,我建议通过 id ASC
而不是 DESC
进行排序,以便引擎可以利用主键排序的好处,即 ASC
,直到进一步实施。
【讨论】:
【参考方案2】:正如您所遇到的,拥有索引并不意味着它会被使用。这适用于每个数据库——索引选择取决于查询优化器。正如您所尝试的,强制索引并不意味着您将获得最快的结果。
因此,查询缓存可能对您没有帮助 - 查询计划可能会被缓存,因此甚至不考虑索引。
MySQL 每个语句只使用一个索引,因此覆盖索引(多列)是个好主意,但您必须对其进行测试才能确定。
【讨论】:
【参考方案3】:您在 [Seller] 上的非集群索引可能有太多碎片,并且您的统计数据可能已过时,那么查询优化器可能不会选择最佳查询计划。检查碎片,更新统计信息,或者在卖家上重新构建你的非集群索引,当然如果你也可以为这个查询创建覆盖索引,如果这个查询被用户频繁使用,那么它是值得的。创建覆盖索引时,请确保最终用户最常使用的顺序。就像在您的查询中一样,覆盖索引应该在 [seller->col1->col3->col4]
【讨论】:
以上是关于为啥 MySQL 不使用索引?的主要内容,如果未能解决你的问题,请参考以下文章