1-问题
查询:
sql
EXPLAIN SELECT * FROM orders WHERE user_id = 1234;
发现:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | orders | ALL | 99520 | 10 | Using where |
分析:
-
select_type = SIMPLE:说明这是一个简单查询,没有子查询或UNION
-
table = orders :查询的表就是
orders -
partitions = NULL:没有分区
-
type = ALL:这是最关键的,表示执行计划是 全表扫描。也就是说它没有用索引,而是把整张表都扫一遍 -
possible_keys = NULL:没有可用的索引
-
key = NULL:关键,实际使用的索引也是空的,说明没有用索引 -
key_len = NULL:索引长度为空
-
ref = NULL:没有引用索引
-
rows = 99520:关键,预估需要扫描大约 99,520 行数据 -
filtered = 10:表示大约只有 10% 的数据符合条件
-
Extra = Using where :说明是靠
WHERE user_id = 1234这个条件来过滤
查询在orders表上做了全表扫描 ,效率比较低。如果orders表很大,性能会很差。原因是user_id字段没有索引,所以数据库只能把整张表读一遍再过滤
2-优化
- 执行计划显示 type = ALL,也就是全表扫描
possible_keys = NULL,说明数据库认为没有合适的索引可以用- 查询条件是WHERE user_id = 1234`
可以新增user_id索引,提高查询速度
sql
# 新增索引
CREATE INDEX idx_user_id ON orders(user_id);
# 再次运行
EXPLAIN SELECT * FROM orders WHERE user_id = 1234;
结果为:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | orders | ref | idx_user_id | idx_user_id | 9 | const | 8 | 100 |
分析:
-
type = ref :这表示查询使用了非唯一索引(普通索引),通过索引来定位行,而不是全表扫描。相比之前的
ALL,性能提升很大 -
possible_keys = idx_user_id :数据库识别到可以用
idx_user_id这个索引 -
key = idx_user_id :实际使用的索引就是你刚建的
idx_user_id -
key_len = 9 :索引字段的长度(这里是
user_id的存储长度) -
ref = const :说明查询条件是一个常量(
user_id = 1234),直接用这个值去索引里查 -
rows = 8:数据库预估只需要扫描大约8行,而不是之前的99,520行
-
filtered = 100:表示这些行几乎全部符合条件