2013-07-18 65 views
0

使用的filesort我有很简单的表:在简单查询

CREATE TABLE `navigation` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `parent_id` int(11) unsigned DEFAULT NULL, 
    `title` varchar(255) NOT NULL COMMENT 'Название ссылки', 
    `priority` tinyint(3) NOT NULL COMMENT 'Параметр сортировки' 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 

只有41行。我也有非常简单的查询:

mysql> EXPLAIN SELECT t.id, t.parent_id, t.title, t.priority FROM navigation t ORDER BY t.priority ASC; 
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra   | 
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 
| 1 | SIMPLE  | t  | ALL | NULL   | NULL | NULL | NULL | 41 | Using filesort | 
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 
1 row in set (0.00 sec) 

我该如何避免使用filesort?或者是不可能的? 我已阅读了很多关于SO的主题,但无法理解正确的答案。 谢谢。

+0

只有41行,你为什么在意? – eggyal

+0

因为我现在只有41行,但是在生产中有很多行。生产服务器(MySQL)也使用filesort。 –

回答

2

我该如何避免使用filesort?或者是不可能的?我已经阅读了很多关于SO的主题,但无法理解正确的答案。

您需要在priority列的索引:

ALTER TABLE navigation ADD INDEX (priority); 

但是,机会是,MySQL将计算出使用这种指数排序结果最终将超过filesort更贵(因为前者将涉及顺序读取索引文件以便在表中执行随机I/O,而后者将涉及顺序读取表并对结果执行内存中排序)。您可以覆盖这一评估与index hint

SELECT t.id, t.parent_id, t.title, t.priority 
FROM  navigation t FORCE INDEX FOR ORDER BY (priority) 
ORDER BY t.priority ASC; 

一个covering index将完全避免需要读入表,因此可以立即从仅仅通过索引文件依次行走返回结果;它会因此有可能通过查询优化器没有进一步提示选择:

ALTER TABLE navigation ADD INDEX(priority, id, parent_id, title); 

哪种方法适合你将取决于应用程序的需求,但要记住Knuth的格言:“过早的优化是一切罪恶的根源”。

1

要避免一个文件夹,大多数时候你应该添加一个索引。在你的情况下,这将意味着priority列的索引。你可以这样做如下:

ALTER TABLE `navigation` ADD INDEX (`priority`); 

注意,即使该指数仍可能是一个文件排序被用作实际上可能比使用索引快。对于41行,可能会出现这种情况,即使定义了索引也是如此。

1

根据this blog postfilesort发生在每次对未索引列进行排序时发生。它与文件系统中发生的实际分类无关。 随着Erik's answer中的描述,你应该摆脱它。