我有一张带有日期时间(DATE)和位(PUBLIC)的汽车。
现在我想采用DATE排序的行和PUBLIC = 1,所以我使用:
select
c.*
from
Cars c
WHERE
c.PUBLIC = 1
ORDER BY
DATE DESC
但不幸的是,当我使用解释来查看发生了什么时,我有这个:
1 SIMPLE a ALL IDX_PUBLIC,DATE NULL NULL NULL 103 Using where; Using filesort
当我只有100行时,需要0.3毫秒来获取这些数据。还有其他方法可以禁用filesort吗?
如果我去索引,我的索引(PUBLIC,DATE)不是唯一的。
表格def:
CREATE TABLE IF NOT EXISTS `Cars` (
`ID` int(11) NOT NULL auto_increment,
`DATE` datetime NOT NULL,
`PUBLIC` binary(1) NOT NULL default '0'
PRIMARY KEY (`ID`),
KEY `IDX_PUBLIC` (`PUBLIC`),
KEY `DATE` (`PUBLIC`,`DATE`)
) ENGINE=MyISAM AUTO_INCREMENT=186 ;
答案 0 :(得分:1)
如果您按日期订购,则需要进行排序。如果按日期没有索引,则将使用filesort。摆脱这种情况的唯一方法是在日期添加索引或不按顺序执行。
此外,文件排序并不总是暗示文件将在磁盘上排序。如果表足够小或者排序缓冲区足够大,它可以在内存中对其进行排序。它只意味着表本身必须进行排序。
看起来你已经有了一个日期索引,并且由于你在where子句中使用PUBLIC,MySQL应该能够使用该索引。但是,优化器可能已经决定,因为您有这么少的行,所以不值得使用索引。尝试向表中添加10,000行,重新分析它,看看是否会改变计划。
答案 1 :(得分:1)
您需要在(public, date)
这样,MySQL
将对public
进行过滤,并对date
进行排序。
从EXPLAIN
我发现(public, date)
上没有综合索引。
相反,您在public
和date
上有两个不同的索引。至少,这就是他们的名字IDX_PUBLIC
和DATE
所说的。
<强>更新强>
您public
列不是BIT
,而是BINARY(1)
。它是一种字符类型,使用字符比较。
将整数与字符进行比较时,MySQL
会将后者转换为前者,反之亦然。
这些查询会返回不同的结果:
CREATE TABLE t_binary (val BINARY(2) NOT NULL);
INSERT
INTO t_binary
VALUES
(1),
(2),
(3),
(10);
SELECT *
FROM t_binary
WHERE val <= 10;
---
1
2
3
10
SELECT *
FROM t_binary
WHERE val <= '10';
---
1
10
将public
列更改为bit
或将查询重写为:
SELECT c.*
FROM Cars c
WHERE c.PUBLIC = '1'
ORDER BY
DATE DESC
,我。即将字符与字符进行比较,而不是整数。