Yii2.0.14中索引生效关键在于查询能否实际使用,需通过EXPLAIN验证type、key、Extra字段,联合索引须按等值→范围→排序顺序设计,并避免隐式转换、函数操作等导致失效的写法。

Yii2.0.14 中数据库索引要真正起效,关键不在“有没有建”,而在于“查询时能不能用上”。很多项目升级到 2.0.14 后性能反而下降,不是框架变慢了,而是旧写法在新版本下暴露了索引失效问题——比如隐式类型转换、未覆盖排序字段、联合索引顺序错位等。
查 SQL 前先看执行计划
别信 Yii 日志里那句 “Executed in 8ms”。它不告诉你扫描了多少行,更不反映是否走了索引。必须手动验证:
- 用 $query->createCommand()->getRawSql() 拿出原生 SQL,再在 MySQL 客户端执行 EXPLAIN
- 重点关注 type 列:ALL 或 index 是危险信号;range、ref、eq_ref 才算合理走索引
- 确认 key 列非空,且值是你期望的索引名;若为空,说明没命中任何索引
- 留意 Extra 里的 Using filesort 或 Using temporary,意味着 ORDER BY 或 GROUP BY 触发了额外开销
联合索引必须按查询模式排字段顺序
比如常见查询:WHERE status = 1 AND created_at > '2025-01-01' ORDER BY created_at DESC。这时索引应建为 (status, created_at),而非反过来。
- 等值条件(=、IN)放最左,范围条件(>、BETWEEN、LIKE 'abc%')放右
- 排序字段如果参与 WHERE,尽量纳入联合索引末尾;如果只用于 ORDER BY 且未出现在 WHERE 中,单独建索引效果有限
- 避免冗余:已有 (a,b) 就不必再建 (a);(a,b,c) 覆盖了 (a,b),但不能替代 (b,c)
Yii 查询写法直接影响索引是否生效
框架封装再好,底层仍是 SQL。几个高频踩坑点:
-
字符串字段传整型参数:如
$query->andWhere(['user_id' => 123]),而 user_id 是 VARCHAR 类型 → 触发隐式转换,索引失效 -
对字段做函数操作:如
andWhere(['>=', 'DATE(create_time)', '2025-01-01'])→ 应改用 BETWEEN 或 >= + - 模糊查询写成 %abc:LIKE '%关键词' 无法使用索引;LIKE '关键词%' 才可能命中
- SELECT * + JOIN 多表:尤其分页场景,建议用延迟关联或子查询先取 ID,再关联查详情,避免回表放大 IO
配套优化不能少:schemaCache 和 asArray()
索引再好,也架不住框架反复查元数据、反复构造 ActiveRecord 对象:
- 务必开启 enableSchemaCache => true,并确保 schemaCache 指向有效缓存组件(如 redis 或 apcu)
- 非必要不返回对象:用 asArray() 取数组,减少内存和序列化开销
- 批量操作别用循环 save(),改用 batchInsert() 或事务包裹多条 insert
- 关闭调试模式:defined('YII_DEBUG') or define('YII_DEBUG', false); 必须在入口文件第一行,且不可被后续配置覆盖


















