我们的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 with limit语句上使用索引?
发布于 2013-03-18 11:28:30
添加到ORDER BY DESC + LIMIT子句的is a common problematic situation for mysql优化器中的多个可能的索引情况,以及强制索引实际上可能是合法的极少数情况之一。
还请注意,您的子句IN (...)给优化器带来了额外的麻烦。
如果你真的不需要它,我建议按id ASC而不是DESC排序,这样引擎就可以利用主键排序的好处,在进一步实现之前,主键排序是ASC。
发布于 2013-03-18 11:01:22
正如您所遇到的,拥有索引并不意味着它将被使用。这适用于每个数据库--索引选择取决于查询优化器。正如您已经尝试过的,强制索引并不意味着您将获得最快的结果。
此后,查询缓存可能不会对您有所帮助--查询计划可能会被缓存,因此甚至不会考虑索引。
MySQL每条语句只使用一个索引,所以一个覆盖索引(多列)将是一个好主意,但您必须对其进行测试才能确定。
发布于 2013-03-18 12:14:52
您在卖方上的非集群索引可能有太多碎片,并且您的统计数据可能已过期,那么查询优化器可能不会选择最佳查询计划。检查碎片,更新统计数据,或者在卖家上重建你的非集群索引,当然如果你也可以为这个查询创建覆盖索引,如果这个查询经常被用户使用,并且它的成本是值得的。创建覆盖索引时,请确保订单是最终用户最常用的。与查询中一样,覆盖索引应该在seller>col1->col3->col4上
https://stackoverflow.com/questions/15469076
复制相似问题