在简单查询中使用filesort

时间:2013-07-18 14:34:38

标签: mysql sql explain

我的表非常简单:

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的主题,但无法理解正确的答案。 谢谢。

3 个答案:

答案 0 :(得分: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 :(得分:1)

要避免使用文件排序,大多数情况下您应该添加索引。在您的情况下,这意味着priority列上的索引。您可以按如下方式执行此操作:

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

请注意,即使使用此索引,仍然可以使用文件排,因为它实际上可能比使用索引更快。即使定义了索引,也可能有41行。

答案 2 :(得分:1)

每次在未编制索引的列上排序时,都会发生this blog post filesort。它与文件系统中发生的实际排序无关。 根据{{​​3}}中的描述,你应该摆脱它。