使用"FileSort"的Mysql Order by子句

Aka*_*ash 9 mysql indexing explain database-performance

我有一个表格结构

comment_id primary key
comment_content 
comment_author
comment_author_url
Run Code Online (Sandbox Code Playgroud)

当我点火查询时

explain SELECT * FROM comments  ORDER BY comment_id
Run Code Online (Sandbox Code Playgroud)

它将结果输出为

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  comments    ALL     NULL    NULL    NULL    NULL    22563   Using filesort
Run Code Online (Sandbox Code Playgroud)

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

ype*_*eᵀᴹ 13

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

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

MyISAM表只有B树索引,所以如果查询使用了这个索引,它必须读取整个索引并且它将具有comment_id所需顺序的值(这真的很好)但是它必须同时读取表(不太好)获得所有其他想要的列.因此,优化器认为,既然它将读取表,为什么不扫描它并执行filesort?您可以通过尝试来测试:

SELECT comment_id FROM comments  ORDER BY comment_id ;
Run Code Online (Sandbox Code Playgroud)

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


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

附加索引当然需要与磁盘一样多的磁盘空间.


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


ale*_*oot 8

无论何时无法从索引执行排序,它都是一个文件排序.

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

SELECT comment_id, comment_content, comment_author, comment_author_url 
FROM comments  
ORDER BY comment_id
Run Code Online (Sandbox Code Playgroud)

它会正确使用索引.也许可能是mysql的bug ...

  • 从MariaDB中的MyISAM将存储引擎更改为InnoDB,现在看起来效果很好 (2认同)