2

我们的 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 | 
+----+-------------+------------------+-------+--------------------+---------+---------+------+------+-------------+

当 I 时force index (Seller),它非常快,0.7 秒。

而且我发现如果不使用limit语句,这个查询会使用Seller索引,会非常快。为什么 MySQL 不使用 index on Sellerwith limit 语句?

4

3 回答 3

1

正如您所遇到的,拥有索引并不意味着它会被使用。这适用于每个数据库——索引选择取决于查询优化器。正如您所尝试的,强制索引并不意味着您将获得最快的结果。

之后,查询缓存可能对您没有帮助——查询计划可以被缓存,因此甚至不考虑索引。

MySQL 每个语句只使用一个索引,因此覆盖索引(多列)是一个好主意,但您必须对其进行测试才能确定。

于 2013-03-18T03:01:22.007 回答
1

添加到ORDER BY DESC+LIMIT子句的多个可能的索引情况对于 mysql的优化器来说是一个常见的问题情况,并且强制索引实际上可能是合法的极少数情况之一。

另请注意,您的子句IN (...)对优化器来说是一个额外的麻烦。

如果你真的不需要它,我建议按 id 排序,ASC而不是DESC这样引擎可以使用主键排序的好处,ASC直到进一步实施。

于 2013-03-18T03:28:29.713 回答
1

您在 [Seller] 上的非集群索引可能有太多碎片,并且您的统计信息可能已经过时,那么查询优化器可能不会选择最佳查询计划。检查碎片,更新统计信息,或者在卖家上重新构建你的非集群索引,当然如果你也可以为这个查询创建覆盖索引,如果这个查询被用户频繁使用,并且值得付出代价。创建覆盖索引时,请确保最终用户最常使用的顺序。就像在您的查询中一样,覆盖索引应该在 [seller->col1->col3->col4]

于 2013-03-18T04:14:51.897 回答