ITPub博客

首页 > 数据库 > MySQL > 组合索引作用

组合索引作用

原创 MySQL 作者:xuexiaogang 时间:2024-11-19 22:18:40 0 删除 编辑

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

以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;

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


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/637517/viewspace-3050625/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
OracleACE/PostgreSQLACE/阿里云MVP/腾讯云TVP/墨天轮 MVP/TiDBMVA/数盟会华东区长老/OpenTenBase社区委和技术委委员/架构师技术同盟名人堂成员上海地区理事会成员/if社区联合发起人/《DBA实战手记》作者/公众号:四海内皆兄弟

注册时间:2013-07-01

  • 博文量
    422
  • 访问量
    953381