复合索引应按等值字段在前、范围字段在后、排序字段连续靠后排列;php中函数操作、隐式类型转换、前置like、or不当使用等会导致索引失效;需用explain验证key、rows和extra字段确认真实生效。

索引不是加得越多越快,而是要让每条高频查询语句都能走索引、少回表、不失效。盲目加索引反而拖慢写入,还可能让优化器选错执行计划。
复合索引字段顺序怎么排
字段顺序直接决定索引能不能被用上。等值条件字段放前面,范围条件(BETWEEN、>、LIKE 'abc%')放后面,排序字段(ORDER BY)尽量靠后但需连续。
- 错误示例:
ALTER TABLE orders ADD INDEX idx_time_status (created_at, status)—— 如果查询是WHERE status = 'paid' AND created_at > '2025-01-01',这个索引完全无效 - 正确写法:
ALTER TABLE orders ADD INDEX idx_status_time (status, created_at),等值先匹配status,再在结果集内按时间范围扫描 - 如果还要
ORDER BY id DESC,且只查id和status,可扩展为(status, created_at, id),构成覆盖索引
哪些 PHP 查询写法会让索引直接失效
PHP 拼 SQL 时稍不注意,索引就形同虚设。常见失效点都在 WHERE 子句里,和 PHP 变量拼接强相关。
-
WHERE YEAR(created_at) = ?→ 改成WHERE created_at >= ? AND created_at (传入 <code>'2025-01-01'和'2026-01-01') -
WHERE phone = ?,但 PHP 传的是字符串'13812345678',而字段是INT类型 → 触发隐式转换,索引失效;应统一类型或改字段为VARCHAR(11) -
WHERE name LIKE CONCAT('%', ?, '%')→ 前导通配符必全表扫描;如必须模糊查,考虑FULLTEXT或前置分词+ES -
WHERE status IN (?, ?) OR type = ?→ OR 分支没共用索引时容易退化;优先拆成UNION,或确保每个分支都有对应索引
EXPLAIN 看什么才说明索引真生效
光看 type 是 ref 或 range 不够,关键要看三处:
-
key字段是否显示你建的索引名,而不是NULL或其他索引 -
rows是否明显小于表总行数(比如百万级表,rows是几千才算有效过滤) -
Extra里不能有Using filesort(说明排序没走索引)或Using temporary(说明用了临时表),尤其当出现Using where; Using index才是理想覆盖索引状态
执行前加 EXPLAIN 是硬要求,别信“我加了索引应该就快了”——PHP 里用 PDO::prepare() 后绑定参数,再对生成的最终 SQL 执行 EXPLAIN,才反映真实情况。
最易被忽略的一点:索引不是一劳永逸的。数据分布变化(比如某 status 值从 5% 占比涨到 95%)、查询模式迁移(新增一个带 user_id + category 的报表接口)、甚至 MySQL 小版本升级都可能让原有索引失效。定期抓慢查询日志 + ANALYZE TABLE + 检查 information_schema.statistics 中的 INDEX_COMMENT 和使用频次,比堆砌索引重要得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











