PHP 数据库索引失效常见原因总结

6次阅读

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

PHP 数据库索引失效常见原因总结

php 本身不直接管理数据库索引,索引是否生效取决于 sql 查询的写法和底层数据库(如 mysqlpostgresql)的执行计划。所谓“索引失效”,其实是查询未走预期索引,导致全表扫描或性能下降。以下是实际开发中高频导致索引失效的典型原因及应对建议。

WHERE 条件中对索引列做函数操作或运算

数据库无法使用索引进行快速定位,一旦在索引列上使用函数、表达式或类型转换,优化器通常放弃使用该索引。

  • 错误示例: WHERE YEAR(create_time) = 2024create_time 有索引)→ 索引失效
  • 正确写法: WHERE create_time >= '2024-01-01' AND create_time
  • 其他常见陷阱:UPPER(name) = 'ABC'id + 1 = 100CAST(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 = 1WHERE a = 1 AND b = 2WHERE a = 1 AND b = 2 AND c = 3
  • 注意:范围查询(>, , <code>BETWEEN)之后的列无法用于索引查找,例如 WHERE a = 1 AND b > 2 AND c = 3c 不参与索引查找

隐式类型转换或字符集不一致

当查询条件与字段定义类型不一致(如字符串字段传入数字)、或连接表字段字符集/排序规则不同,数据库可能放弃使用索引。

  • 典型问题: user_idVARCHAR 类型,却写成 WHERE user_id = 123 → 触发隐式转换
  • 跨表 JOIN 失效: 表 A 的 nameutf8mb4_unicode_ci,表 B 的同名字段是 utf8mb4_general_ci → 可能无法使用索引
  • 防范方式: 保持参数类型与字段一致(如加引号:WHERE user_id = '123');统一字符集与 collation
text=ZqhQzanResources