【问题标题】:Why is MySQL using filesort in this case?为什么 MySQL 在这种情况下使用文件排序?
【发布时间】:2011-05-22 08:09:56
【问题描述】:

表结构:

CREATE TABLE IF NOT EXISTS `newsletters` 
(
    `id` int(11) NOT NULL auto_increment,
    `last_update` int(11) default NULL,
    `status` int(11) default '0',
    `message_id` varchar(255) default NULL,
    PRIMARY KEY  (`id`),
    KEY `status` (`status`),
    KEY `message_id` (`message_id`),
    KEY `last_update` (`last_update`)
) 
ENGINE=MyISAM DEFAULT CHARSET=latin1;

查询:

SELECT id, last_update
FROM newsletters
WHERE status = 1
ORDER BY last_update DESC 
LIMIT 0, 100
  • newsletters 表有超过 300 万条记录
  • 查询需要 26 秒 来执行

查询说明:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  newsletters range   status  status  5   NULL    3043354 Using where; Using filesort

那么为什么不使用filesort,它又是如何使用range 查询的呢?

【问题讨论】:

    标签: mysql sql performance optimization


    【解决方案1】:

    它使用filesortlast_update 进行排序。您可以通过将索引更改为status, last_update 来避免文件排序,因此 MySQL 会以正确的顺序找到状态为 1 的所有行。

    要进一步优化,请将索引更改为status, last_update, id。这允许 MySQL 仅通过查看索引来满足查询,而无需查找表。

    CREATE INDEX idx_newsletters_status
    ON newsletters(status, last_update, id);
    

    【讨论】:

    • KEY 应该应用与 INDEX 相同的索引。
    • 做到了,我是优化/索引方面的业余爱好者,所以我并没有真正考虑尝试索引多个列。 @Baez:你能理解你的意思吗?
    • @gAMBOOKa:为了形象化哪个索引对你最有帮助,试着想一想如果你是计算机,什么列表,按什么顺序对最有帮助,并且不得不迅速找到正确的记录,并返回所要求的信息。在这种情况下,您需要一个所有记录的列表(因为每个索引都需要包含所有记录)首先按状态排序(因为您只对 1 感兴趣),然后按 last_update(这样您就可以快速获得其中的前 100 个)。如果将 id 添加到列表中,则无需返回主表即可获取所有信息。
    • 这是一种非常直观的解释方式。所以基本上,我应该按照从左到右消除最多行的顺序添加索引,对吗?
    猜你喜欢
    • 1970-01-01
    • 2012-06-20
    • 2017-01-07
    • 2015-05-20
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多