9

我有一个像这样的表结构

comment_id primary key
comment_content 
comment_author
comment_author_url

当我触发查询时

explain SELECT * FROM comments  ORDER BY comment_id

它将结果输出为

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  comments    ALL     NULL    NULL    NULL    NULL    22563   Using filesort

为什么找不到我定义为主键的索引?

4

2 回答 2

16

这不是因为它不能使用索引。这是因为优化器认为不使用索引并执行 filesort 1会更快。您应该在 MyiSAM 和 InnoDB 表中看到不同的行为。

InnoDB 将PRIMARY键创建为集群键(UNIQUE如果未定义主键,则为第一个键),这可用于具有ORDER BY pkWHERE pk BETWEEN low AND high因为所需的所有值都在此集群键和连续位置中的查询(集群键表) .

MyISAM 表只有 B-tree 索引,所以如果查询使用这个索引,它必须读取整个索引,并且它的comment_id值会按照想要的顺序(这真的很好)但是它也必须读取表(不太好)获得所有其他想要的列。所以,优化器认为既然要读取表,为什么不扫描它并进行文件排序呢?您可以通过尝试进行测试:

SELECT comment_id FROM comments  ORDER BY comment_id ;

它将使用索引并且不进行文件排序,因为查询只需要存储在索引中的值。


如果您想在 MyiSAM 中实现类似(与 InnoDB)的行为,您可以尝试在其上创建索引(comment_id, comment_content, comment_author, comment_author_url),然后尝试查询。所有需要的值都可以在索引上找到并且顺序正确,因此不会执行文件排序。

附加索引当然需要几乎与表一样多的磁盘空间。


1:文件排序并不总是坏的,这并不意味着文件保存在磁盘上。如果数据的大小很小,则在内存中执行。

于 2012-08-12T10:28:04.220 回答
10

任何时候无法从索引执行排序,它都是文件排序。

这里奇怪的是,您应该在该字段上有索引,因为它是主键(并且主键列被隐式索引),在测试数据库上进行测试我只是注意到 MySQL 在您执行 a 时使用 FileSort SELECT *,这是一个没有意义的行为(我知道),但如果你以这种方式重写你的查询:

SELECT comment_id, comment_content, comment_author, comment_author_url 
FROM comments  
ORDER BY comment_id

它将正确使用索引。也许可能是mysql的一个错误......

于 2012-08-12T09:12:01.883 回答