为什么MySQL仅使用复合索引而不使用单独的索引?

时间:2019-01-17 07:36:53

标签: mysql indexing

我有下表

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 aindex b,并且比综合索引要小一些。

即使我错了,它也至少应首先使用index a,然后使用文件排序对b进行排序。

这种排序运算符真的不能使用分离的索引吗?如果是,请解释为什么它不起作用。如果没有,您有什么解决方案可以让它与单独的索引一起使用?预先感谢。

编辑

例如,我有100行。我可以先使用index a对它们进行排序。然后在每个具有相同a值的组中,我可以使用index b对它们进行排序。

为什么这种方法不能在MySQL上工作?

1 个答案:

答案 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并且由于某种原因而无法添加复合索引时,这将非常有用。