Yii渴望加载 - 致命错误:内存不足

问题描述 投票:1回答: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'),但我找不到问题的根源。

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

memory eager-loading yii
1个回答
0
投票

你正遭受爆炸行数组合的爆炸。看看this question,它以较小的规模描述了同样的问题。基本上,您正在运行具有多个一对多连接的大型查询,类似于:

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 can do that

$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;

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

© www.soinside.com 2019 - 2024. All rights reserved.