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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么MySQL只使用复合索引而不是单独的索引?相关的知识,希望对你有一定的参考价值。

我有下表

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然后使用filesort来排序b。

这种排序运算符真的不能使用分离的索引吗?如果是,请解释为什么它不起作用。如果不是,您是否有任何解决方案让它与单独的索引一起使用?提前致谢。

编辑

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

为什么这种方式无法在mysql上运行?

答案

当索引(复合或非复合)用于“排序”时,MySQL按顺序读取数据,并且根本不进行排序。多个索引无法做到这一点。

按顺序读取1-st索引然后进行文件排序是可能的,但它不太可能更快,所以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并且由于某种原因无法添加复合索引时,这可能很有用。

以上是关于为什么MySQL只使用复合索引而不是单独的索引?的主要内容,如果未能解决你的问题,请参考以下文章

数据库 | SQL语法优化方法及实例详解

MySQL联合索引生效的条件、索引失效的条件

MySQL:制作 3 个字段的复合索引,还是制作 3 个单独的索引?

mysql的索引和执行计划

Mysql优化之执行计划查看

mysql加了性别变慢