多列索引对单列也有用吗?

时间:2016-06-04 12:15:47

标签: mysql indexing

我对多个索引组的顺序感到困惑。

看看这个:

. . . WHERE col1 = ? AND col2 = ? AND col3 = ?

在上面的查询中,我必须在(col1, col2, col3)上创建一个三列索引。现在我想知道,多索引在其他地方有用吗?例如,此查询:

. . . WHERE col1 = ? AND col2 = ?

我应该为这个^创建另一个双列索引(col1, col2),还是这个三列索引也足够了?

这个查询怎么样:

. . . WHERE col2 = ? AND col3 = ?

或者这个:

. . . WHERE col2 = ? AND col1 = ?

他们都需要分离的索引,或者一个多索引对所有索引都足够吗?

实际上我正在试图理解索引的顺序是如何工作的?

3 个答案:

答案 0 :(得分:3)

MySQL在使用多列索引方面有很好的documentation

首先要注意的是,您的where条件包含相同的条件;类型转换和排序规则差异也会影响索引的使用。条件也由AND连接。 OR阻碍了索引的使用。

从索引的角度来看,列的顺序(具有相等性)无关紧要。所以,对于这些条件:

WHERE col1 = ? AND col2 = ? AND col3 = ?

这六个索引中的任何一个都是最佳的:(col1, col2, col3)(col1, col3, col2)(col2, col1, col3)(col2, col3, col1)(col3, col1, col2)(col3, col2, col1)。他们"覆盖" where条款。

作为旁注:最多只有一个不等式可以最佳地使用索引,这是索引中使用的最后一列。

where子句也可以使用较小的索引,例如(col1)(col2, col3)。在这种情况下,使用索引进行一些过滤,对于其余的,引擎需要在数据页中查找数据以获取所需的字段。

索引也可用于仅使用键子集的where条件 - 但必须从左到右使用键。因此,(col1, col2, col3)上的索引可用于这些条件:

where col1 = ? and col2 = ? and col3 = ?
where col1 = ? and col2 = ?
where col2 = ? and col1 = ?
where col1 = ?

它不会被用于没有col3的条件。并且,它可以(部分地)用于诸如以下的条件:

where col1 = ? and col2 = ? and col4 = ?

答案 1 :(得分:2)

您可以从左到右使用复合索引

所以如果你有col1,col2,col3

的索引

适用于

col1, col2 , col3
col1, col2
col1

但不适用于

col2, col3
col3

<强>样品

我创建了一个包含3列和10000行的表

INSERT INTO tab3
SELECT NULL,seq,seq+1,seq+2 FROM seq_1_to_10000;

没有索引的EXPLAIN

MariaDB []> explain select * from tab3 where col1 = 100 AND col2 = 101 AND col3 = 102;
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
|    1 | SIMPLE      | tab3  | ALL  | NULL          | NULL | NULL    | NULL | 9991 | Using where |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.04 sec)

创建超过3列的索引

MariaDB []> ALTER TABLE tab3 add key idx_tab3 (col1,col2,col3);
Query OK, 0 rows affected (0.27 sec)
Records: 0  Duplicates: 0  Warnings: 0

再次尝试选择,仅使用1行

MariaDB []> explain select * from tab3 where col1 = 100 AND col2 = 101 AND col3 = 102;
+------+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref               | rows | Extra       |
+------+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
|    1 | SIMPLE      | tab3  | ref  | idx_tab3      | idx_tab3 | 15      | const,const,const |    1 | Using index |
+------+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)

使用col1和col2尝试WHERE,也可以

MariaDB []> explain select * from tab3 where col1 = 100 AND col2 = 101;
+------+-------------+-------+------+---------------+----------+---------+-------------+------+-------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref         | rows | Extra       |
+------+-------------+-------+------+---------------+----------+---------+-------------+------+-------------+
|    1 | SIMPLE      | tab3  | ref  | idx_tab3      | idx_tab3 | 10      | const,const |    1 | Using index |
+------+-------------+-------+------+---------------+----------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

使用col1和col3尝试WHERE,不能完美运行

MariaDB []> explain select * from tab3 where col1 = 100 AND col3 = 102;
+------+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra                    |
+------+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+
|    1 | SIMPLE      | tab3  | ref  | idx_tab3      | idx_tab3 | 5       | const |    1 | Using where; Using index |
+------+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

答案 2 :(得分:2)

当您在(col1, col2, col3)上创建索引时,它应该适用于以下情况,因为对于这两个条件col1是索引中的第一个键

. . . WHERE col1 = ? AND col2 = ? AND col3 = ?

. . . WHERE col1 = ? AND col2 = ?

. . . WHERE col2 = ? AND col3 = ?WHERE col2 = ? AND col1 = ?同样不起作用。在这种情况下,您必须创建一个单独的索引。

但是在你的情况下,我觉得最好是为每列而不是复合索引创建单独的单个索引。