作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
数据库是一个系统(应用)最重要的资产之一,所以我们的数据库将从以下几个数据库来进行介绍。
MySQL(本章节)
PostgreSQL
Redis
Etcd
上个小节我们对索引做了一个基本介绍,本小节我们就通过一个实际案例来理解这个索引。
测试数据
表结构
mysql> desc test_data;
+---------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| value | varchar(255) | YES | | NULL | |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
| random_number | int(11) | YES | | NULL | |
+---------------+--------------+------+-----+-------------------+----------------+
测试数据
mysql> select count(*) from test_data ;
+----------+
| count(*) |
+----------+
| 8437686 |
+----------+
1 row in set (3.18 sec)
mysql> select * from test_data limit 1;
+----+--------------+---------------------+---------------+
| id | value | created_at | random_number |
+----+--------------+---------------------+---------------+
| 1 | Test value 0 | 2025-09-16 22:39:20 | 984 |
+----+--------------+---------------------+---------------+
1 row in set (0.00 sec)
测试查询
1.使用id进行查询,可以看出来我们查询还是很快的。
mysql> select * from test_data where id=8000000;
+---------+--------------------+---------------------+---------------+
| id | value | created_at | random_number |
+---------+--------------------+---------------------+---------------+
| 8000000 | Test value 1512488 | 2025-09-18 22:36:59 | 778 |
+---------+--------------------+---------------------+---------------+
1 row in set (0.02 sec)
2.通过value查询,我们查询同样一条记录(虽然结果有多条),但是查询时间已经达到2.27秒,是通过id的查询的113倍。虽然MYSQL默认的慢查询时间是10秒,但是实际上很多业务系统配置慢查都是1-3秒。而且这个800w的数据其实并不多,而且表结构相对简单。
mysql> select * from test_data where value="Test value 1512488";
+---------+--------------------+---------------------+---------------+
| id | value | created_at | random_number |
+---------+--------------------+---------------------+---------------+
| 7999074 | Test value 1512488 | 2025-09-18 22:36:49 | 530 |
| 8000000 | Test value 1512488 | 2025-09-18 22:36:59 | 778 |
| 8001855 | Test value 1512488 | 2025-09-18 22:37:26 | 135 |
| 8002430 | Test value 1512488 | 2025-09-18 22:37:32 | 706 |
+---------+--------------------+---------------------+---------------+
4 rows in set (2.27 sec)
3.查看索引,这里可以看到这里有一个主键索引,所以通过id查询速度很快,通过查询value,没有索引数据达到一定程度以后就会变慢。
mysql> SHOW INDEX FROM test_data\G;
*************************** 1. row ***************************
Table: test_data
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 7587917
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>
4.添加索引,由于有比较多的历史数据,所以这里添加耗费了比较长的时间。
mysql> CREATE INDEX idx_test_data_value ON test_data (value);
Query OK, 0 rows affected (1 min 1.10 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
5.再次查询索引,可以看到已经有我们刚才添加索引,所以我这里的数据比你并不是唯一的,所以这里的索引量只有1597267,这个Cardinality越接近真实数据索引加速效果越好。
*************************** 2. row ***************************
Table: test_data
Non_unique: 1
Key_name: idx_test_data_value
Seq_in_index: 1
Column_name: value
Collation: A
Cardinality: 1597267
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.00 sec)
6.再次查询数据(有索引的情况),可以看到我们查询数据时间已经等于0(并不是没有时间,而是太短这里不显示),查询速度得到了明显的提升。
mysql> select * from test_data where value="Test value 1512488";
+---------+--------------------+---------------------+---------------+
| id | value | created_at | random_number |
+---------+--------------------+---------------------+---------------+
| 7999074 | Test value 1512488 | 2025-09-18 22:36:49 | 530 |
| 8000000 | Test value 1512488 | 2025-09-18 22:36:59 | 778 |
| 8001855 | Test value 1512488 | 2025-09-18 22:37:26 | 135 |
| 8002430 | Test value 1512488 | 2025-09-18 22:37:32 | 706 |
+---------+--------------------+---------------------+---------------+
4 rows in set (0.00 sec)