问题描述
|
我正在改造网站的内部邮件系统,遇到了一些我不理解的问题。表格如下:
CREATE TABLE `mails` (
`id` bigint(12) unsigned not null auto_increment,`recipient_id` mediumint(8) unsigned not null,`date_sent` datetime not null,`status` enum(\'unread\',\'read\',\'deleted\') default \'unread\',PRIMARY KEY(`id`),INDEX(`recipient_id`,`status`,`date_sent`),CONSTRAINT FOREIGN KEY (`recipient_id`) REFERENCES `members` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE `mail_contents` (
`mail_id` bigint(12) unsigned not null,`sender_id` mediumint(8) unsigned not null,`subject` varchar(150) default \'\',`content` text not null,CONSTRAINT FOREIGN KEY (`sender_id`) REFERENCES `members` (`id`) ON DELETE CASCADE,CONSTRAINT FOREIGN KEY (`mail_id`) REFERENCES `mails` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
这是查询:
SELECT *
FROM mails AS m
LEFT JOIN mail_contents AS mc ON mc.mail_id = m.id
WHERE recipient_id = 66
AND status != \'deleted\'
ORDER BY date_sent DESC
LIMIT 40\\G
在查询上的说明显示\“使用位置;使用索引;使用文件排序\”。但是,如果我将查询更改为此:
SELECT *
FROM mails AS m
LEFT JOIN mail_contents AS mc ON mc.mail_id = m.id
WHERE recipient_id = 66
AND status = \'sent\'
ORDER BY date_sent DESC
LIMIT 40\\G
EXPLAIN显示“使用位置;使用索引”。由于某种原因,在第一个查询中使用!=会导致文件排序,但是在第二个查询中使用=不会使用文件排序。我很好奇到底是什么引起了差异?
解决方法
等于是包含的,而!=是排除的。 MySQL查找包容性结果的效率更高。
在这种情况下,“使用文件排序”实际上是负数,因为这意味着查询需要使用临时表进行排序(该表是文件),然后返回结果。
,
INDEX(recipient_id
,status
,date_sent
)在第二个查询中用于排序,因为前两列是固定的,并且排序依据是使用第三个rd5ѭ=> nofilesort
因为status
不是常数(!= \'deleted\'
),所以不能在第一个查询中使用它。
更多信息在这里:按优化排序