1

我有一张带有日期时间(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 毫秒。有没有其他方法可以禁用文件排序?

如果我去索引我有索引 (PUBLIC, DATE) 不是唯一的。

表定义:

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 ;
4

2 回答 2

1

如果您按日期订购,则需要排序。如果没有按日期索引,则将使用文件排序。摆脱这种情况的唯一方法是在日期上添加索引或不按顺序进行。

此外,文件排序并不总是意味着文件将在磁盘上排序。如果表足够小或排序缓冲区足够大,它可能会在内存中对其进行排序。这只是意味着必须对表本身进行排序。

看起来您已经有一个日期索引,并且由于您在 where 子句中使用了 PUBLIC,因此 MySQL 应该能够使用该索引。但是,优化器可能已经决定,由于您的行数太少,因此不值得为索引烦恼。尝试向表中添加大约 10,000 行,重新分析它,看看是否会改变计划。

于 2009-09-24T12:08:09.770 回答
1

你需要有一个复合索引(public, date)

这样,MySQL将过滤public和排序date

从你的EXPLAIN我看到你没有在(public, date).

相反,您有两个不同的索引 onpublic和 on date。至少,这就是他们的名字IDX_PUBLICDATE说明。

更新:

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列更改为 abit或将您的查询重写为:

SELECT  c.*
FROM    Cars c
WHERE   c.PUBLIC = '1'
ORDER BY 
        DATE DESC

,即比较字符与字符,而不是整数。

于 2009-09-24T12:09:46.740 回答