2012-10-25 16 views
3

我有一张拒绝使用索引的表,它总是使用filesort。MySQL在索引化的TIMESTAMP列上使用filesort

表是:

 
CREATE TABLE `article` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `Category_ID` int(11) DEFAULT NULL, 
    `Subcategory` int(11) DEFAULT NULL, 
    `CTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `Publish` tinyint(4) DEFAULT NULL, 
    `Administrator_ID` int(11) DEFAULT NULL, 
    `Position` tinyint(4) DEFAULT '0', 
    PRIMARY KEY (`ID`), 
    KEY `Subcategory` (`Subcategory`,`Position`,`CTimestamp`,`Publish`), 
    KEY `Category_ID` (`Category_ID`,`CTimestamp`,`Publish`), 
    KEY `Position` (`Position`,`Category_ID`,`Publish`), 
    KEY `CTimestamp` (`CTimestamp`), 
    CONSTRAINT `article_ibfk_1` FOREIGN KEY (`Category_ID`) REFERENCES `category` (`ID`) 
) ENGINE=InnoDB AUTO_INCREMENT=94290 DEFAULT CHARSET=utf8 

查询是:

 
SELECT * FROM article ORDER BY `CTimestamp`; 

的解释是:

 
+----+-------------+---------+------+---------------+------+---------+------+-------+----------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra   | 
+----+-------------+---------+------+---------------+------+---------+------+-------+----------------+ 
| 1 | SIMPLE  | article | ALL | NULL   | NULL | NULL | NULL | 63568 | Using filesort | 
+----+-------------+---------+------+---------------+------+---------+------+-------+----------------+ 

当我删除了 “ORDER BY”,那么所有工作正常。所有其他指数(子类别,职位等)在其他查询中工作正常。不幸的是,时间戳拒绝使用,即使使用我的简单选择查询。我确信我在这里错过了一些重要的东西。

如何让MySQL使用时间戳索引?

谢谢。

+0

当您尝试创建索引并放置您尝试创建索引的代码时,会出现什么错误(在我的网络中,ajax被阻止,因此我不能在那里发表评论,这就是为什么我在这里问)。 –

回答

5

在这种情况下,MySQL没有使用您的索引进行排序,这是一件好事。 为什么?你的表只包含64k行,平均行宽约26字节(如果我添加了列大小的权利),所以磁盘上的表总大小应该在2MB左右。 从磁盘读取2MB数据到内存(可能只需1-2次磁盘操作或寻道),然后只是在内存中执行filesort(可能是quicksort的变化)是非常便宜的。

如果MySQL按照您的意愿通过索引顺序进行检索,则必须执行64000次磁盘查找操作,一个接一个地记录!这本来会非常非常缓慢。

当您可以使用它们快速跳转到大文件中的已知位置并读取少量数据时(如在WHERE子句中),索引可以很好。但是,在这种情况下,这不是个好主意 - 而MySQL并不愚蠢!

如果你的表非常大(超过内存大小),那么MySQL肯定会开始使用你的索引 - 这也是件好事。

+0

因此'使用filesort'实际上意味着它在内存中完成*?非常令人困惑的名字。 –

+0

是的,它是在大小为@@ sort_buffer_size的缓冲区中完成的(在我的机器上它是16MB) – mvp

+0

谢谢。如何报告磁盘**上的排序**? (如果sort_buffer_size小于要排序的结果) –

0

那么,你总是可以提示索引。将您的查询更改为

SELECT * FROM article use index (CTimestamp); 

这会强制MySQL使用索引进行查询。解释:

1, 'SIMPLE', 'article', 'ALL', '', '', '', '', 1, 100.00, '' 

没有要查看的文件,因为使用的索引是CTimestamp,结果应该相应地排序。

或者,您可以通过子句保持您的订单,但强制使用索引:

SELECT * FROM article force index (CTimestamp) order by CTimestamp; 

的问题仍然是陌生的,虽然。你有没有考虑过把它发布到官方的MySQL帮助论坛?

编辑:你好像是in good company
编辑:强制索引seems to work out well

相关问题