为什么MySQL在这种情况下使用filesort?

为什么MySQL在这种情况下使用filesort?,mysql,sql,performance,optimization,Mysql,Sql,Performance,Optimization,表格结构: 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

表格结构:

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
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
查询:

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
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
  • 时事通讯
    表格有超过300万条记录
  • 查询执行时间超过26秒
查询解释:

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
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
,它是一个怎样的
范围
查询呢?

它使用
filesort
上次更新
进行排序。通过将索引更改为
status,last\u update
,您可以避免文件排序,这样MySQL会以正确的顺序查找状态为1的所有行

要进一步优化,请将索引更改为
状态,最后更新,id
。这使得MySQL只需查看索引即可满足查询,而无需进行表查找

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

键应该应用与索引相同的索引。这样做了,我是一个优化/索引的业余爱好者,所以我没有真正考虑尝试索引多个列@贝兹:你能理解你的意思吗?@gAMBOOKa:为了直观地看到什么索引对你最有帮助,试着想想如果你是计算机,什么列表,什么顺序对你最有帮助,并且必须快速找到正确的记录,并返回所要求的信息。在这种情况下,您需要一个所有记录的列表(因为每个索引都需要包含所有记录),首先按状态排序(因为您只对1感兴趣),然后按上次更新排序(这样您可以快速获得其中的前100个)。如果您将id添加到列表中,那么您可以获得所有信息,而无需返回主表。这是一种非常直观的解释方式。所以基本上,我应该按从左到右删除最多行的顺序添加索引,对吗?