【问题标题】:Mysql Order by clause using "FileSort"Mysql Order by 子句使用“FileSort”
【发布时间】:2012-08-08 21:27:48
【问题描述】:

我有一个类似的表结构

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

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

【问题讨论】:

    标签: mysql indexing database-performance explain


    【解决方案1】:

    不是因为它不能使用索引。这是因为优化器认为不使用索引并进行文件排序会更快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:文件排序并不总是坏的,并不意味着文件保存在磁盘上。如果数据量小,则在内存中执行。

    【讨论】:

    • 为什么如果您在 select 子句中运行按名称列出所有字段的查询,而不是使用星号运算符,它会使用索引?看我的回答...
    • @aleroot:您是否同时使用 MyISAM 和 InnoDB 进行了测试?
    • @aleroot:那我可能错了。表中有多少行?我也会做一些测试。
    • 你的意思是说MyISAM在这样的查询中表现比InnoDB好,而且生产服务器有超过1,00,000行,在这种情况下使用索引是否正确?
    • 不,我不是那个意思。如果表是 InnoDB,SELECT * FROM table ORDER BY pk 将只需要按顺序读取表并且不进行文件排序。但是,为什么您需要读取所有数百万行的查询呢?
    【解决方案2】:

    任何时候不能从索引执行排序,它就是文件排序。

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

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

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

    【讨论】:

    • 感谢调查,我在Mysql 5.1版本中试过了,升级有帮助吗?计划使用 MariaDB
    • 我不知道我有版本:5.1.63,你可以尝试升级或在MariaDB上看看......
    • @Akash 也许最好迁移到 PostgreSQL :-)
    • 已将存储引擎从 MariaDB 中的 MyISAM 更改为 InnoDB,现在看起来效果很好
    • 当然,他们的默认存储引擎似乎是 InnoDB
    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 2011-09-17
    • 2014-06-05
    • 2013-11-10
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多