90%的Yii性能问题源于可定位环节:数据库未走索引、debug开启、localhost DNS解析慢、日志写满磁盘或N+1查询;应优先检查db.log中Query/Duration,用explain分析SQL,禁用debug模块及info级日志,将localhost改为127.0.0.1。

Yii 应用变慢,别急着换框架——90% 的性能问题出在可定位、可修复的具体环节:数据库没走索引、debug 模块开着、DNS 解析卡在 localhost、日志写满磁盘、或 N+1 查询在循环里悄悄放大延迟。先抓最可能的点,再逐层下钻。
怎么快速确认是不是数据库查询拖慢了?
打开 runtime/logs/app.log 或 runtime/logs/db.log,搜 Query: 和 Duration:,看有没有单条 SQL 耗时超过 100ms;更准的方法是直接用 EXPLAIN 分析高频接口对应的 SQL:
- 在控制器里加一行:
$users = User::find()->where(['status' => 1])->explain()->all();,看返回的type是不是ALL(全表扫描) - 用
createCommand()->getRawSql()拿出真实 SQL,粘到 MySQL 客户端手动跑EXPLAIN FORMAT=TREE,重点关注key是否为空、rows是否远超预期 - 检查是否启用了
'enableProfiling' => true和'enableParamLogging' => true,否则日志里只有WHERE id = ?,看不到实际参数值,无法判断深分页或隐式类型转换问题
为什么开了 debug 工具栏,API 接口就明显变卡?
debug 模块本身不响应 API 请求,但它注册的全局事件监听器(比如 beforeAction、afterAction、DB 执行钩子)全程运行,每个请求额外增加 20–80ms 开销。这不是“界面慢”,是整个请求生命周期被拖长。
- 生产环境必须确保
YII_DEBUG为false,且YII_ENV不等于'dev' -
config/web.php中 debug 模块只能出现在YII_ENV_DEV条件分支里,不能无条件注册 - 开发阶段若只需查 SQL,可用
Yii::getLogger()->flush()+Yii::getLogger()->messages手动捞日志,避免挂载完整 debug 模块 - 禁用不需要的面板,比如把
'profiling' => false关掉,'db' => yii\debug\panels\DbPanel::class留着就行
localhost 连数据库慢,真是 PHP 版本或配置问题?
不是。这是 DNS 解析行为导致的典型延迟:PHP 7.4+ 在 Windows 或某些 Linux 环境下遇到 localhost,会同时尝试 IPv6(::1)和 IPv4(127.0.0.1),超时后才 fallback,光解析就卡几百毫秒。
- 立刻把数据库配置里的
'dsn' => 'mysql:host=localhost;...'改成'dsn' => 'mysql:host=127.0.0.1;...' - 别信“重启服务就好”——改完要清
runtime/cache/,否则 schema 缓存可能仍指向旧连接 - 如果用 Docker,确保容器内
/etc/hosts有127.0.0.1 localhost映射,否则改了也没用
日志写太多、缓存没开、循环查库,哪个更容易被忽略?
日志写太多最隐蔽。它不报错、不中断流程,只默默吃 CPU 和 I/O,尤其当 'levels' => ['error', 'warning', 'info'] 全开着,又没配 rotateSize 和 maxLogFiles 时,runtime/logs/ 下几百 MB 的日志文件会让每次 fopen 都变慢。
- 线上必须关掉
'info'级别,只留'error'和'warning' - 在
log组件里加'rotateSize' => 1024 * 1024 * 5(5MB)和'maxLogFiles' => 5 - N+1 查询常藏在视图渲染或 API 序列化中,比如
foreach ($posts as $post) echo $post->author->name;—— 这种代码在 debug 工具栏的 DB 面板里会显示“执行了 23 次查询”,但没人盯着看



















