EXPLAIN输出表明未使用我的索引


9

我只在done_status(done_status = INT)上设置了带有索引的表:

在此处输入图片说明

当我使用时:

EXPLAIN SELECT * FROM reminder  WHERE done_status=2

我回来了:

id select_type表的类型possible_keys键key_len参考行额外
1 SIMPLE提醒ALL done_status NULL NULL NULL 5使用

但是当我发出以下命令时:

EXPLAIN SELECT * FROM reminder  WHERE done_status=1

我得到以下返回:

id select_type表的类型possible_keys键key_len参考行额外
1 SIMPLE提醒参考ref done_status done_status 4 const 2   

EXPLAIN让我发现,它采用5行,第二次2行。

我认为索引没有被使用,如果我第一次正确地理解它,它应该给我3行。我做错了什么?

SHOW INDEX FROM reminder

表非唯一键名Seq_in_index列名归类基数子部分打包为空Index_type注释Index_comment
提醒1 done_status 1 done_status A 5 NULL NULL BTREE

解释扩展:

id select_type表的类型possible_keys键key_len ref行已过滤额外
1个SIMPLE提醒ref done_status done_status 4 const 2 100.00

show warnings 没有显示任何感兴趣的内容。


相信我,索引有效。但是我无法在屏幕快照中轻松看到任何内容-您可以执行“从您的表中显示索引”吗?

是的,编辑了我的问题

请为模型使用glorify \ G并解释计划结果,它应该更具可读性
ajreal

出于兴趣,您可以使用“解释扩展”和“显示警告”重复进行此操作,这将显示实际的SQL mysql选择

@ajreal是什么荣耀?

Answers:


4

您误解了“行”字段是什么。它是mysql估计满足您的查询需要读取的行数。该值可能非常不准确。这并不意味着这是结果中的行数-或mysql读取的实际行数


所以?我在哪里说呢?优化器选择了什么呢?索引仍然有效。

@ajreal但这并不意味着索引已损坏。只是优化器会选择(在其心中)最有效的查询数据方法。我以为OP期望EXPLAIN中的rows列是准确的。这并不意味着索引已损坏-只是mysql选择不使用它(可能)。

1
@ajreal:我在你的观点上有遗漏。解释的行列与索引无关吗?Mysql选择不使用索引(也许所有数据都在单个页面中)。不确定我是否理解您的观点?5行表上的查询优化将产生一些“奇数”结果,因为它几乎与优化方式无关。


在这种情况下,谁在乎优化器选择什么索引?索引本身没有错,因为优化器感觉不需要它-它有什么关系?

3

最初的执行平原肯定不会使用索引,
它可能是索引上的information_schema.statistics在执行某些写操作后没有赶上数据,或者长时间未访问表。

如此处说明: -MySQL Query Optimizer从哪里读取索引统计信息?

对于第二个执行计划,似乎information_schema.statistics已经赶上并解决了NULL基数问题。

因此,是根据索引优化器执行查询。

对于具有小行的表,这无关紧要。
但是数据会增长,开发人员应始终对此进行检查,
并在索引上遇到基数为空时执行必要的分析表。


0

第一个执行计划不使用索引。

MySQL参考网站

有时,即使索引可用,MySQL也不使用索引。发生这种情况的一种情况是优化器估计使用索引将需要MySQL访问表中很大比例的行。(在这种情况下,表扫描可能会更快,因为它需要更少的查找。)但是,如果这样的查询使用LIMIT只检索某些行,则MySQL仍然使用索引,因为它可以更快地找到返回结果的几行。

如果您的表只有5行,而您的查询选择了3行,则MySQL优化程序会认为扫描整个表更为有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.