我有下表
CREATE TABLE `test` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL
);
我需要执行以下查询
SELECT * FROM `test` ORDER BY a, b LIMIT 1;
如果我添加复合索引
ALTER TABLE `t_test` ADD INDEX a_b(`a`, `b`);
有效
> EXPLAIN SELECT * FROM `test` ORDER BY a, b LIMIT 1;
+------+-------------+-------+-------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | test | index | NULL | a_b | 8 | NULL | 1 | |
+------+-------------+-------+-------+---------------+------+---------+------+------+-------+
但是如果我分别添加两个索引
ALTER TABLE `t_test` ADD INDEX a(`a`), ADD INDEX b(`b`);
失败
> EXPLAIN SELECT * FROM `test` ORDER BY a, b LIMIT 1;
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | test | ALL | NULL | NULL | NULL | NULL | 2 | Using filesort |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
即使我添加了FORCE INDEX
,它也不起作用。
据我个人所知,它应该同时使用index a
和index b
,并且比综合索引要小一些。
即使我错了,它也至少应首先使用index a
,然后使用文件排序对b进行排序。
这种排序运算符真的不能使用分离的索引吗?如果是,请解释为什么它不起作用。如果没有,您有什么解决方案可以让它与单独的索引一起使用?预先感谢。
例如,我有100行。我可以先使用index a
对它们进行排序。然后在每个具有相同a
值的组中,我可以使用index b
对它们进行排序。
为什么这种方法不能在MySQL上工作?
答案 0 :(得分:0)
当索引(复合索引或非复合索引)用于“排序”时,MySQL按顺序读取数据,并且根本不进行排序。使用多个索引是不可能的。
可以按顺序读取第1个索引,然后进行文件排序,但这不可能更快,因此MySQL不会这样做。
如果您确实需要这样做,可以使用如下子查询:
SELECT ...
FROM (
SELECT primary_key
FROM table1
ORDER BY field1
LIMIT 15
) tmp
JOIN table1 t ON t.primary_key = tmp.primary_key
ORDER BY field1, field2
当您拥有LIMIT
并且由于某种原因而无法添加复合索引时,这将非常有用。