做演示文稿时,很多人会从数据库或Excel里拉数据生成图表。可有时候明明建了索引,查询速度却越来越慢,甚至像没建过一样——这就是典型的“索引失效”问题。
为什么索引会突然失效?
比如你负责公司月度销售汇报,每次从后台导出几千条记录筛选区域和时间。为了加快加载,你在“区域”字段加了索引。但某次更新后发现查询变慢,检查执行计划才发现索引没被用上。
常见原因之一是在索引字段上做了函数操作。例如写成:WHERE YEAR(create_time) = 2024,数据库无法直接匹配时间字段的索引,只能全表扫描。
避免对索引列进行运算或函数处理
正确做法是把条件改写为范围查询:
<?php
// 错误方式:导致索引失效
$sql = "SELECT * FROM sales WHERE MONTH(sale_date) = 5";
// 正确方式:使用 BETWEEN 保持索引有效
$sql = "SELECT * FROM sales WHERE sale_date BETWEEN '2024-05-01' AND '2024-05-31'";
?>别让隐式类型转换拖慢查询
另一个容易忽略的情况是字符串和数字混用。假设你的订单表用字符型存储订单编号(如ORD001),而你在SQL中写了:WHERE order_id = 123,系统可能自动转类型,导致索引失效。
解决办法很简单:确保比较值类型一致。如果字段是字符串,查询时加上引号:WHERE order_id = 'ORD123'。
联合索引顺序不能乱
创建了 (dept, gender, age) 的复合索引,并不意味着三个字段随便怎么查都能走索引。比如只按 age 查询,大概率用不上这个索引。
要遵循最左前缀原则。下列查询能命中索引:
WHERE dept = '技术部'WHERE dept = '技术部' AND gender = '男'
但下面这种就很难生效:
SELECT * FROM employees WHERE gender = '女' AND age = 28;模糊查询尽量别在开头用 %
想查姓名包含“小明”的员工,写成 LIKE '%小明%',数据库没法利用索引,只能逐行匹配。
如果业务允许,改成前缀匹配效果明显提升:LIKE '小明%'。或者考虑引入全文索引或搜索引擎如Elasticsearch来替代。
统计信息过期也会误导执行计划
数据量变化大之后,MySQL等数据库可能因为统计信息未更新,误判是否使用索引。可以手动运行:ANALYZE TABLE 表名; 来刷新统计,帮助优化器做出更优选择。
实际工作中,不妨定期检查那些原本很快但现在变慢的查询语句,结合 EXPLAIN 分析执行路径,看看是不是走了全表扫描。
发现问题后调整SQL写法,配合合理的索引设计,大多数性能瓶颈都能缓解。毕竟没人希望PPT演讲时,后台还在拼命加载数据。