MySQL执行计划中,Key有值,还是很慢怎么办?
MySQL执行计划中,Key有值,还是很慢怎么办?
月伴飞鱼如果 执行计划中
key
有值,type=index
,但查询仍然很慢。说明索引并没有按照预期优化查询性能,而是发生了全索引扫描(Index Full Scan)。
这种情况的核心问题可能出在索引使用方式或查询优化上。
如何正确分析 SQL 执行计划?
在 EXPLAIN
结果中,几个重要的字段:
字段 | 含义 | 重点 |
---|---|---|
id |
查询执行的步骤 | 越大表示执行顺序越靠后 |
type |
访问类型 | 影响查询效率的关键 |
possible_keys |
可能使用的索引 | 可供查询选择的索引 |
key |
实际使用的索引 | 如果是 NULL ,说明没用索引 |
rows |
预计扫描行数 | 值越大说明查询性能越差 |
Extra |
额外信息 | 是否 Using index 或 Using where; Using index |
问题分析:type=index
代表什么?
如果
type=index
,说明进行了全索引扫描(Index Full Scan),即遍历整个索引树,而不是通过索引加速查询。这个情况类似于 全表扫描(type=ALL),只是扫描的是索引而非数据表。
示例:
1 | EXPLAIN SELECT col1 FROM my_table WHERE col2 = 'xxx'; |
可能返回:
1 | +----+-------+---------------+----------+--------------------------+ |
在 Extra
中 出现 Using where; Using index
,意味着:
SQL 确实用了索引
idx_col2
(key 列)。但查询仍然需要回表或扫描整个索引树。
可能的原因:索引未能高效筛选数据。
可能导致查询慢的原因
索引失效:没有满足最左前缀匹配
- 复合索引
(a, b, c)
,如果WHERE
仅b, c
,则索引失效。 - 建议:调整查询,确保
WHERE
子句符合索引最左匹配原则。
- 复合索引
索引筛选性差,导致大量数据扫描
- 低选择性索引(如
status=1
这种大量重复值)会导致扫描大量行。 - 优化:换更高区分度的列建立索引。
- 低选择性索引(如
回表查询导致性能下降
EXTRA
中如果出现Using where; Using index
,意味着:- 查询需要回表(即索引不覆盖查询列)
优化方案:创建覆盖索引,减少回表操作
1
2
3
4-- 假设查询 `SELECT col1 FROM my_table WHERE col2 = 'xxx'`
-- 现有索引 idx_col2(col2)
-- 改进:创建联合索引 (col2, col1) 避免回表
CREATE INDEX idx_col2_col1 ON my_table (col2, col1);
使用
LIKE '%xx'
或者函数操作列
,导致索引失效WHERE UPPER(name) = 'JOHN'
使得name
索引失效- 解决方案:避免对索引列使用函数,或者考虑创建函数索引
解决方案
问题 | 解决方案 |
---|---|
索引未匹配 WHERE |
调整 SQL 确保最左匹配 |
索引选择性差 | 选择更具区分度的索引 |
需要回表查询 | 用覆盖索引优化 |
LIKE '%xx' 导致全索引扫描 |
改进索引或考虑全文索引(FULLTEXT ) |
总结
当 key
有值但查询仍然很慢:
重点关注
type
和Extra
字段,看是否Using where; Using index
可能是全索引扫描(
type=index
)导致的,意味着索引没加速查询检查索引是否最左匹配、是否需要回表、索引选择性是否合理
尝试优化 SQL 结构,或创建覆盖索引,减少回表扫描