求助:Yii2 ActiveRecord 的 with() 在循环里被我玩坏了
今天 profile.log 出现一段我看不懂的现象,列表页一刷出来 200+ 条 SQL,按理说我已经用了 with():
$posts = ForumPost::find()
->with(["user", "category"])
->limit(20)
->all();
foreach ($posts as $p) {
// 这里我又调用了 $p->replies — 没在 with() 里
$count = count($p->replies);
}
问题是:replies 没写进 with(),循环里每次都一条 SQL。Schema cache 开了也救不了 N+1。
我现在的怀疑
- 加
with("replies"),但是 reply 行很多,会不会 over-fetch? - 改
count用聚合 SQL:->select([..., "COUNT(reply.id) AS reply_count"]),但 GROUP BY 写起来挺难看。 - 直接读
$p->reply_count字段(已经在表里维护了)—— 这是最干净的,但今天不是用 reply_count 当例子,我是想问:当我真的需要在循环里用关联数据时,Yii 的最佳实践是啥?
你们怎么排 N+1 的
- Yii Debug Toolbar 的 DB panel?
- profile.log + grep?
- EXPLAIN 一条条看?
求一个不太花俏但能用的工作流。