索引失效指查询未走预期索引导致全表扫描,主因是对索引列使用函数、运算或类型转换;如year(create_time)=2024使索引失效,应改用create_time>='2024-01-01' and create_time

PHP 本身不直接管理数据库索引,索引是否生效取决于 SQL 查询的写法和底层数据库(如 MySQL、PostgreSQL)的执行计划。所谓“索引失效”,其实是查询未走预期索引,导致全表扫描或性能下降。以下是实际开发中高频导致索引失效的典型原因及应对建议。
WHERE 条件中对索引列做函数操作或运算
数据库无法使用索引进行快速定位,一旦在索引列上使用函数、表达式或类型转换,优化器通常放弃使用该索引。
-
错误示例:
WHERE YEAR(create_time) = 2024(create_time有索引)→ 索引失效 -
正确写法:
WHERE create_time >= '2024-01-01' AND create_time - 其他常见陷阱:
UPPER(name) = 'ABC'、id + 1 = 100、CAST(status AS CHAR) = '1'
模糊查询以通配符 % 开头
LIKE 匹配中,若左值为索引列且模式以 % 开头(如 LIKE '%abc'),无法利用 B+ 树索引的有序性,只能全表扫描。
-
失效场景:
WHERE name LIKE '%admin'(即使name有索引) -
可走索引的情况:
WHERE name LIKE 'admin%'或name LIKE 'ad%in'(前缀匹配) - 如需全文检索,考虑
FULLTEXT索引或 Elasticsearch 等专用方案
联合索引未遵循最左前缀原则
联合索引(如 (a, b, c))要求查询条件从左到右连续匹配,跳过左侧列会导致右侧列索引失效。
立即学习“PHP免费学习笔记(深入)”;
-
失效示例:
WHERE b = 2 AND c = 3→ 不走索引;WHERE a = 1 AND c = 3→ 仅用到a列索引 -
有效使用:
WHERE a = 1、WHERE a = 1 AND b = 2、WHERE a = 1 AND b = 2 AND c = 3 - 注意:范围查询(
>,, <code>BETWEEN)之后的列无法用于索引查找,例如WHERE a = 1 AND b > 2 AND c = 3中c不参与索引查找
隐式类型转换或字符集不一致
当查询条件与字段定义类型不一致(如字符串字段传入数字)、或连接表字段字符集/排序规则不同,数据库可能放弃使用索引。
-
典型问题:
user_id是VARCHAR类型,却写成WHERE user_id = 123→ 触发隐式转换 -
跨表 JOIN 失效: 表 A 的
name是utf8mb4_unicode_ci,表 B 的同名字段是utf8mb4_general_ci→ 可能无法使用索引 -
防范方式: 保持参数类型与字段一致(如加引号:
WHERE user_id = '123');统一字符集与 collation











