我对多个索引组的顺序感到困惑。
看看这个:
. . . WHERE col1 = ? AND col2 = ? AND col3 = ?
在上面的查询中,我必须在(col1, col2, col3)
上创建一个三列索引。现在我想知道,多索引在其他地方有用吗?例如,此查询:
. . . WHERE col1 = ? AND col2 = ?
我应该为这个^创建另一个双列索引(col1, col2)
,还是这个三列索引也足够了?
这个查询怎么样:
. . . WHERE col2 = ? AND col3 = ?
或者这个:
. . . WHERE col2 = ? AND col1 = ?
他们都需要分离的索引,或者一个多索引对所有索引都足够吗?
实际上我正在试图理解索引的顺序是如何工作的?
答案 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 = ?
同样不起作用。在这种情况下,您必须创建一个单独的索引。
但是在你的情况下,我觉得最好是为每列而不是复合索引创建单独的单个索引。