我的表非常简单:
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 :(得分: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}}中的描述,你应该摆脱它。