mysql 即使有索引也会进行文件排序 -- 我该如何解决

mysql file sort happens even with indexes -- How can I fix

我在下面有一个简单的查询,如果table,我可以确保它运行得很快。我对查询做了一个解释,它说使用哪里;使用文件排序。有没有办法摆脱文件排序?数据现在只有大约 25 项;但最终可能会增加 300 或更多。

mysql> show create table phppos_categories;
+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table             | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_categories | CREATE TABLE `phppos_categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `phppos_categories_ibfk_1` (`parent_id`),
  KEY `name` (`name`),
  KEY `parent_id` (`parent_id`),
  CONSTRAINT `phppos_categories_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `phppos_categories` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM (`phppos_categories`) WHERE `parent_id` = 5 ORDER BY `name` asc;
+----+-----------+-------------------+
| id | parent_id | name              |
+----+-----------+-------------------+
|  3 |         5 | Basketball Shoes  |
|  7 |         5 | Basketball Shorts |
+----+-----------+-------------------+
2 rows in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM (`phppos_categories`) WHERE `parent_id` = 5 ORDER BY `name` asc;
+----+-------------+-------------------+------+------------------------------------+--------------------------+---------+-------+------+-----------------------------+
| id | select_type | table             | type | possible_keys                      | key                      | key_len | ref   | rows | Extra                       |
+----+-------------+-------------------+------+------------------------------------+--------------------------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | phppos_categories | ref  | phppos_categories_ibfk_1,parent_id | phppos_categories_ibfk_1 | 5       | const |    2 | Using where; Using filesort |
+----+-------------+-------------------+------+------------------------------------+--------------------------+---------+-------+------+-----------------------------+
1 row in set (0.00 sec)

mysql> 

您看到 'using filesort' 是因为您按 name 列排序,这是一个 varchar(255) 字段。

ORDER BY `name` asc;

解释报告检查的记录数只有 2,正在使用 parent_id 上的索引。结果集中有 2 行。因此,MySQL没有做任何额外的或不必要的工作。

就我个人而言,在这种情况下,我不会担心尝试摆脱 'using filesort'。即使 table 中有 300 行,您仍然在索引字段 (parent_id) 上使用 where 限制结果集,并且检查的行数将等于结果集中的行数。

您可以通过在 (parent_id, name) 上添加多列索引来删除此处的文件排序。

更改 TABLE phppos_categories 添加索引 (parent_id,name);

一般来说 MySQL 只会在必须使用其中一个索引进行排序时才使用单个索引(如果您只是使用两个索引来查询 table,它可能会使用两个索引使用索引合并,但通常情况并非如此)。解决方案是创建一个覆盖所有需要查询的列的索引。

其次,MySQL 只能对它使用的索引中的最后一列进行 "range" 搜索或 "sort"。之前的任何列都必须完全相等。

在此基础上,我们可以先用parent_id创建一个索引,它有一个完全相等的匹配(=5),然后是你的顺序约束的名字。

要注意的主要事情是您不想添加不必要的索引,并且适合每个可能的查询的索引可能不明智,尤其是考虑到额外的存储 space 和使索引保持最新所需的工作。作为该比较的一部分,您还需要考虑 table 的更新频率。如果它很少更新,那么更多的索引可能不是一个问题。

查看此处了解更多信息: https://dev.mysql.com/doc/refman/5.6/en/order-by-optimization.html