组合索引作用

来源:这里教程网 时间:2026-03-01 18:28:23 作者:

很简单的道理但是日常开发人员还有很多不理解

以MySQL为例,其他数据库也是一样。 样品数据如下: mysql> select * from x; ±-----±-----±-----+ | id | a | b | ±-----±-----±-----+ | 1 | 1 | 1 | | 2 | 1 | 2 | | 3 | 1 | 3 | | 4 | 1 | 4 | | 5 | 1 | 5 | | 6 | 2 | 1 | | 7 | 2 | 2 | | 8 | 2 | 3 | | 9 | 2 | 4 | | 10 | 2 | 5 | | 11 | 3 | 1 | | 12 | 3 | 2 | | 13 | 3 | 3 | | 14 | 3 | 4 | | 15 | 3 | 5 | ±-----±-----±-----+ 15 rows in set (0.00 sec)

对于一个没有索引的列进行查询,就是全表。

mysql> select * from x where id=1; ±-----±-----±-----+ | id | a | b | ±-----±-----±-----+ | 1 | 1 | 1 | ±-----±-----±-----+ 1 row in set (0.00 sec)

Query_time: 0.000832 Lock_time: 0.000011 Rows_sent: 1 Rows_examined: 15 SET timestamp=1732024559; select * from x where id=1;

可以看出查询全表15行,返回1行。(如果全表是1500万呢?)

mysql> show create table x\G *************************** 1. row *************************** Table: x Create Table: CREATE TABLE  x ( id int DEFAULT NULL, a int DEFAULT NULL, b int DEFAULT NULL, KEY  t1 ( a) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.01 sec)

日常就是这样,建立索引的列不用,用的就是那些没索引的列。

有索引就一定对吗?

mysql> select * from x where a=1; ±-----±-----±-----+ | id | a | b | ±-----±-----±-----+ | 1 | 1 | 1 | | 2 | 1 | 2 | | 3 | 1 | 3 | | 4 | 1 | 4 | | 5 | 1 | 5 | ±-----±-----±-----+ 5 rows in set (0.00 sec)

Query_time: 0.001034 Lock_time: 0.000011 Rows_sent: 5 Rows_examined: 5 SET timestamp=1732024476; select * from x where a=1;

可以看出只扫描索引范围的行(5行),返回也是范围所在的行(这里要说,如果索引的范围不是5行而是1000万呢?)。

那么再加一个过滤条件总可以吧?

mysql> select * from x where a=1 and b=1; ±-----±-----±-----+ | id | a | b | ±-----±-----±-----+ | 1 | 1 | 1 | ±-----±-----±-----+ 1 row in set (0.00 sec)

Query_time: 0.001114 Lock_time: 0.000016 Rows_sent: 1 Rows_examined: 5

SET timestamp=1732024492; select * from x where a=1 and b=1;

很明显可以看出只扫描索引范围的行(5行),返回是返回了1行,但是扫描行数还是和上一个场景一样(5行)。(这里要说,如果索引的范围就是1000万呢?)。

正确的做法

以上场景建立一个组合索引

mysql> create index t2 on x (a,b); Query OK, 0 rows affected (0.05 sec)

mysql> show create table x\G *************************** 1. row *************************** Table: x Create Table: CREATE TABLE  x ( id int DEFAULT NULL, a int DEFAULT NULL, b int DEFAULT NULL, KEY  t1 ( a), KEY  t2 ( a, b) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.00 sec)

Query_time: 0.219642 Lock_time: 0.000010 Rows_sent: 1 Rows_examined: 1 SET timestamp=1732024637; select * from x where a=1 and b=1;

返回和扫描的一致。真正起到了两级过滤。而不是只扫描第一列索引的范围,而是精确到第一列和第二列交集的范围。大大缩小了检索范围。

相关推荐