1

Yii 急切加载有问题。我打开用户个人资料页面并使用:

$model=User::model()->with('routes', 'likes', 'comments', 'questions', 'cityname')->findByPk($id);

关系是:

public function relations()
    {
        return array(
            'routes'=>array(self::HAS_MANY, 'Route', 'author_id', 'order'=>'routes.id DESC'),
            'questions'=>array(self::HAS_MANY, 'Question', 'author_id', 'order'=>'questions.id DESC'),
            'comments'=>array(self::HAS_MANY, 'Comment', 'author_id', 'order'=>'comments.id DESC',),
            'likes'=>array(self::HAS_MANY, 'Like', 'author_id', 'order'=>'likes.id DESC'),
            'cityname'=>array(self::BELONGS_TO, 'City', 'city'),
        );
    }

当我在评论表中有大约 70 条(或更多)评论时,我有错误:

Fatal error: Out of memory (allocated 348651520) (tried to allocate 78 bytes) in /home/milk/kolyasya.ru/diplomyii/framework/db/CDbCommand.php on line 516

这个问题的有趣部分是,如果我评论 with() 的任何元素,例如:

$model=User::model()->with('routes', 'likes', 'comments', /* 'questions' */, 'cityname')->findByPk($id);

然后一切正常。

我检查了所有模型中的所有关系并设置了 ini_set('memory_limit', '512M'),但我找不到问题的根源。

也许我需要使用延迟加载?

4

1 回答 1

0

您正遭受行组合数量爆炸式增长的困扰。看一下这个问题,它在较小的范围内描述了相同的问题。基本上,您正在运行一个包含多个一对多连接的大型查询,类似于以下内容:

SELECT ... FROM `User` `t` 
  LEFT JOIN `Route` routes ON t.id = routes.author_id
  LEFT JOIN `Question` questions ON t.id = questions.author_id
  LEFT JOIN `Comment` comments ON t.id = comments.author_id
  LEFT JOIN `Like` likes ON t.id = likes.author_id
  LEFT JOIN `City` city ON t.city = city.id
  WHERE t.id = :id
  ORDER BY routes.id DESC, questions.id DESC, comments.id DESC, likes.id DESC

您可以使用此查询,将其修改为SELECT COUNT(*)并在 phpMyAdmin 中运行它以查看它返回的行数。它将等于路线的数量乘以问题的数量乘以评论的数量乘以该用户创建的喜欢的数量。


HAS_MANY在这种情况下,在单独的查询中获取每个关系会更有效。Yii 可以做到

$model=User::model()
  ->with(array(
     'routes' => array('together' => false),
     'likes' => array('together' => false),
     'comments' => array('together' => false),
     'questions' => array('together' => false),
     'cityname' => array(),
  ))
  ->findByPk($id);

如果你这样做了,Yii 将生成多个内存使用量更少的 SQL 查询,类似于以下内容:

SELECT ... FROM `User` `t` 
  LEFT JOIN `City` `city` ON `t`.`city` = `city`.`id`
  WHERE `t`.`id` = :id;

SELECT ... FROM `Route` `routes`
  WHERE `author_id` = :id
  ORDER by `routes`.`id` DESC;

SELECT ... FROM `Question` `questions`
  WHERE `author_id` = :id
  ORDER BY `questions`.`id` DESC;

SELECT ... FROM `Comment` `comments`
  WHERE `author_id` = :id
  ORDER BY `comments`.`id` DESC;

SELECT ... FROM `Like` `likes`
  WHERE `author_id` = :id
  ORDER BY `likes`.`id` DESC;

结果将像以前一样汇总并返回到您的代码中。

于 2013-07-20T07:23:02.233 回答