mysql数据库中的查询执行效率与索引优化

来源:这里教程网 时间:2026-02-28 20:41:37 作者:

为什么
SELECT *
在大表上会突然变慢

不是因为查询本身复杂,而是数据库被迫做全表扫描。没有合适索引时,MySQL 必须逐行读取磁盘页,I/O 成为瓶颈。尤其当

WHERE
条件字段没建索引、或用了函数/表达式(如
WHERE YEAR(created_at) = 2023
),索引就失效了。

避免在索引列上使用函数、类型转换或运算,例如
WHERE price + 10 > 100
会让
price
索引失效
SELECT *
在宽表中还可能触发临时表和文件排序,用
EXPLAIN
查看
Extra
字段是否出现
Using filesort
Using temporary
联合索引要注意最左前缀原则:对
(a, b, c)
建索引,
WHERE b = 1 AND c = 2
无法命中,但
WHERE a = 1 AND b = 2
可以

EXPLAIN
输出里哪些字段真正影响性能判断

重点关注

type
key
rows
Extra
四个字段,它们直接反映执行路径质量。

type
值从好到差:
const
eq_ref
>
ref
>
range
>
index
>
ALL
;出现
ALL
基本等于全表扫描
key
为空说明没走索引;若非空但
rows
值远大于实际结果数,可能是索引选择性差(比如对性别字段建索引)
Extra
中出现
Using index condition
是好的(ICP 下推),但
Using where; Using index
表示覆盖索引,而
Using filesort
就得警惕:ORDER BY 没走索引或顺序不匹配

什么时候该建联合索引而不是单列索引

当多个字段经常同时出现在

WHERE
ORDER BY
GROUP BY
中,且顺序稳定时,联合索引能显著减少索引数量和维护开销。

例如高频查询是
SELECT name FROM user WHERE status = ? AND city = ? ORDER BY created_at DESC
,优先建
(status, city, created_at)
联合索引,而非三个单列索引
把等值条件字段放前面,范围/排序字段放后面:
(a = ?, b > ?, c ORDER BY)
→ 索引应为
(a, b, c)
,不是
(a, c, b)
注意区分「覆盖索引」需求:如果只查索引字段(如
SELECT status, city FROM user WHERE ...
),联合索引还能避免回表

索引不是越多越好:写入变慢和空间膨胀怎么权衡

每个索引都是 B+ 树,INSERT/UPDATE/DELETE 都要同步更新所有相关索引。业务高峰期大量写入时,过多索引会明显拖慢响应,且占用更多磁盘与内存。

单表索引数建议控制在 5–7 个以内;可通过
information_schema.STATISTICS
查看各索引的
INDEX_COMMENT
和使用频率(需开启
userstat
或用
performance_schema
删除长期未被使用的索引:比如某索引在
sys.schema_unused_indexes
视图中持续多日无记录
TEXT/BLOB 字段不能直接建索引,要用前缀长度(如
content(100)
),但前缀过短会导致重复率高、选择性差
SHOW INDEX FROM orders\G
-- 查看索引字段顺序、是否唯一、基数(Cardinality)等,基数越接近行数,索引区分度越高

索引优化本质是让 MySQL 少读磁盘、少算中间结果。很多“慢查询”背后不是 SQL 写得差,而是数据分布变了、统计信息没更新、或者上线后业务查询模式偏移了——这些细节比“加个索引”更难察觉。

相关推荐