mysql索引的选择与优化策略

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

为什么
WHERE
条件里用了函数,索引就失效了

MySQL 无法对表达式结果直接使用 B+ 树索引做快速查找,比如

WHERE YEAR(create_time) = 2023
WHERE UPPER(name) = 'ABC'
。优化器看到的是函数计算后的值,而索引里存的是原始字段值,二者无法对齐。

实操建议:

改写为范围查询:用
create_time BETWEEN '2023-01-01' AND '2023-12-31 23:59:59'
替代
YEAR()
建生成列 + 索引(MySQL 5.7+):
ALTER TABLE orders ADD COLUMN create_year INT AS (YEAR(create_time)) STORED;<br>CREATE INDEX idx_create_year ON orders(create_year);
避免在索引字段上做任何运算、类型转换或函数调用

ORDER BY
GROUP BY
怎么用好联合索引

MySQL 的联合索引遵循最左前缀原则,但排序和分组还额外依赖“索引有序性”。如果

ORDER BY a, b
,而索引是
(a, c, b)
,那
b
就无法利用索引排序——因为中间插了
c
,破坏了
a,b
的物理连续顺序。

实操建议:

ORDER BY
字段尽量靠前且连续出现在联合索引中,例如
INDEX(a, b, c)
支持
ORDER BY a, b
,但不支持
ORDER BY b, c
GROUP BY
同理,且若含聚合函数(如
COUNT()
),确保分组字段能走索引,否则会触发
Using temporary; Using filesort
如果既要
WHERE a = ?
又要
ORDER BY b
,优先建
INDEX(a, b)
,而不是分开建两个单列索引

什么时候该删掉重复或低效的索引

重复索引指功能完全被另一个索引覆盖,比如已有

INDEX(a, b)
,又建了
INDEX(a)
;低效索引指长期没被
SELECT
使用、却在
INSERT/UPDATE/DELETE
中持续拖慢写性能的索引。

实操建议:

查冗余索引:
SELECT * FROM sys.schema_redundant_indexes;
(需启用
sys
schema)
看索引实际使用率:
SELECT index_name, rows_selected FROM sys.schema_index_statistics WHERE table_name = 'orders';
删除前确认:没有
WHERE b = ?
单独查询(否则
INDEX(a, b)
不能替代
INDEX(b)
高频写入表中,超过 5 个索引就要警惕——每个索引都会增加 B+ 树维护成本

LIKE '%xxx'
真的完全不能走索引吗

以通配符开头的模糊查询(

LIKE '%abc'
)确实无法使用 B+ 树索引的有序结构,但不是所有模糊场景都无解。

实操建议:

后缀匹配可走索引:
LIKE 'abc%'
能用
INDEX(name)
,前提是没加函数或隐式转换
全文索引(
FULLTEXT
)适合长文本关键词搜索,但只支持
MyISAM
InnoDB
(5.6+),且对短词(
倒排表或外部搜索引擎(如 Elasticsearch)更适合复杂模糊、拼音、错别字等需求——MySQL 原生不擅长这个 业务上可考虑前置约束:比如先用精确字段过滤(
status = 'active'
),再对小结果集做
LIKE '%xxx'

索引优化最常被忽略的一点:它不是静态配置,而是随查询模式和数据分布动态变化的。上线后必须定期看

slow_log
sys.statement_analysis
,而不是只靠建表时的预判。

相关推荐