0

我有非常简单的表:

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

4

3 回答 3

2

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

您需要在priority列上建立索引:

ALTER TABLE navigation ADD INDEX (priority);

然而,MySQL 可能会计算出使用这样的索引对结果进行排序最终会比 a 更昂贵filesort(因为前者将涉及顺序读取索引文件以便对表执行随机 I/O,而后者将涉及顺序读取表并对结果执行内存排序)。您可以使用索引提示覆盖此评估:

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

覆盖索引将完全避免读取表的需要,因此只需按顺序遍历索引文件即可立即返回结果;因此,查询优化器可能会在没有进一步提示的情况下选择它:

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

哪种方法适合您将取决于您的应用程序的要求,但请记住 Knuth 的格言:“过早优化是万恶之源”。

于 2013-07-18T14:47:59.327 回答
1

根据这篇博客文章 filesort,每次您对未索引的列进行排序时都会发生这种情况。它与文件系统中发生的实际排序无关。根据Erik 的回答中的描述,您应该摆脱它。

于 2013-07-18T14:45:54.903 回答
1

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

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

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

于 2013-07-18T14:44:26.557 回答