【发布时间】:2014-05-25 03:27:01
【问题描述】:
我现在已经阅读了其他几个关于此的堆栈溢出问题,但仍然没有意义。
我正在尝试使用 sakila 世界测试数据库,这是我的表定义:
CREATE TABLE `City` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
KEY `city_name` (`Name`),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `Country` (`Code`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1
这是我的索引:
mysql> show index from City;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| City | 0 | PRIMARY | 1 | ID | A | 4188 | NULL | NULL | | BTREE | | |
| City | 1 | CountryCode | 1 | CountryCode | A | 465 | NULL | NULL | | BTREE | | |
| City | 1 | city_name | 1 | Name | A | 4188 | NULL | NULL | | BTREE | | |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
我试图理解为什么 MySQL 不使用索引在这里对结果进行排序:
mysql> explain select * from City order by Name asc;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | City | ALL | NULL | NULL | NULL | NULL | 4188 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
我不明白为什么 MySQL 在这种情况下要进行文件排序,很明显城市名称上的索引已经对所有内容进行了排序。
我查看了其他一些问题,人们在他们的索引中使用前缀,这禁止 MySQL 使用该索引进行排序。在名称上创建该索引时,我没有使用前缀。
其他人也希望在 Extra 列中看到“使用索引”。我的理解是这意味着索引“覆盖”了查询,这意味着不需要读取实际表,因为索引具有所有值。所以我不希望在 Extra 列中看到这一点,因为索引仅在名称上,并且还有其他列。
我觉得“使用索引”这个词有点误导,MySQL 可以使用索引来过滤结果,但仍然必须读取表。在这种情况下,“使用索引”不会是 Extra 列的一部分。太误导人了。
有人可以向我解释一下为什么 MySQL 仍在为该查询使用文件排序吗?如果你想知道的话,有 4079 行。
另外,有没有什么明确的方法可以知道 MySQL 使用索引对结果进行排序?
【问题讨论】:
-
优化器看到你要从表中读取所有记录,所以它更喜欢从 PRIMARY 索引而不是二级 city_name 读取。因此 MySQL 必须进行额外的排序。