mysql执行SQL查询时索引使用的优先级是什么_mysql优化规则

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

MySQL 用哪个索引?看
WHERE
条件的最左前缀匹配

MySQL 不会“选最优”,而是按索引定义顺序,从左到右逐列匹配

WHERE
中的等值条件(
=
IN
),一旦遇到范围查询(
>
、<code>BETWEEN
LIKE
前缀不固定)或函数/表达式,后续列就失效。比如索引是
(a, b, c)

WHERE a = 1 AND b = 2 AND c = 3
→ 三列全用上
WHERE a = 1 AND b > 2 AND c = 3
→ 只用到
a
b
c
被跳过(
b
是范围终点)
WHERE b = 2 AND c = 3
→ 索引完全不用(没给
a
WHERE a = 1 AND c = 3
→ 只用
a
c
无法跳过
b

多个索引可选时,MySQL 怎么挑?看
rows
预估和索引区分度

当 WHERE 条件能命中多个索引(比如有

(a)
(a,b)
(a,c)
),优化器会估算每个索引扫描的行数(
rows
字段,来自
EXPLAIN
),选预估成本最低的那个。但这个估算依赖统计信息,可能不准——尤其表数据大、长期未
ANALYZE TABLE
时,容易选错。

高区分度列(如
user_id
)放索引左边,比低区分度列(如
status
)更利于剪枝
ORDER BY
GROUP BY
字段如果能被同一索引覆盖,会优先考虑(避免额外排序)
主键索引(聚簇索引)在回表代价高时可能被降级,即使它“理论上更优”

OR
条件会让索引失效?不一定,但很脆弱

单个

OR
条件(如
WHERE a = 1 OR b = 2
)通常无法走索引,除非两边都独立有索引且满足某些版本限制(MySQL 5.7+ 对部分情况支持索引合并
index_merge
)。但要注意:

index_merge
是备选策略,性能常不如单个复合索引,且
EXPLAIN
显示为
type: index_merge
,不是常规
ref
range
写成
WHERE a = 1 UNION ALL SELECT ... WHERE b = 2
有时反而更快,尤其当两边结果集小
NULL
判断的
OR
(如
a IS NULL OR a = 1
)基本无法优化

哪些“看似合理”的写法会悄悄让索引下线

这些细节在开发中极易忽略,但一上线就拖慢查询:

对索引列用函数:
WHERE YEAR(create_time) = 2024
→ 改成
create_time BETWEEN '2024-01-01' AND '2024-12-31'
隐式类型转换:
WHERE user_id = '123'
user_id
INT
)→ 字符串转数字可能放弃索引,尤其字段有大量值时
LIKE
开头带通配符:
WHERE name LIKE '%abc'
→ 全表扫;
LIKE 'abc%'
才能用索引
在索引列上做运算:
WHERE score * 10 > 100
→ 改成
score > 10

真正难的不是建索引,而是让 SQL 写法始终贴合索引结构——改一行 WHERE,可能让执行计划从毫秒变秒级。

相关推荐