优化查询 - 急切加载会占用太多内存

时间:2014-10-14 18:56:03

标签: php mysql laravel laravel-4 eloquent

我有以下表格:

  • 用户(约1.000行)
  • 粉丝(约100.000行) - 用户有很多粉丝,粉丝属于一个用户
  • 喜欢(大约100.000行 - 用户有很多喜欢,喜欢属于一个用户

现在我想要一张带

的表格
  • 用户名
  • 粉丝数
  • 喜欢的数量

这是一个很大的表,我使用jQuery DataTable将它与pagnition一起使用,但这是关于服务器端的。

我已经建立了所有的关系,然后把表放在桌子上:

$users = User::get();

foreach ($users as $user) {
echo $user->name;
echo $user->fans()->count();
echo $user->likes()->count();
}

这是很多查询,我想优化。我的第一次尝试是使用Eager Loading。

$users = User::with('fans', 'likes')->get();

但这对服务器内存来说似乎很苛刻。在我的本地环境中,我有16 MB的memoriy大小的PHP脚本。它总是试图分配更多。

这是正常的吗? 是简单地为脚本提供更多内存的最佳解决方案吗? 我还能如何优化我的查询?

1 个答案:

答案 0 :(得分:5)

如果您只想计算记录数量,那么只计算所有记录是没有意义的,现在您可以获得201000行。你应该添加:

public function fansCountRelation()
{
    return $this->hasOne('Fan')->selectRaw('user_id, count(*) as count')
        ->groupBy('user_id');
}


public function likesCountRelation()
{
    return $this->hasOne('Like')->selectRaw('user_id, count(*) as count')
        ->groupBy('user_id');
}

public function getLikesCountAttribute()
{

    return $this->likesCountRelation ?
        $this->likesCountRelation->count : 0;
}

public function getFansCountAttribute()
{

    return $this->fansCountRelation ?
        $this->fansCountRelation->count : 0;
}

到您的User模型,现在您只会获得1000个用户行+粉丝和喜欢的汇总数据。

现在你可以使用:

$users = User::with('fansCountRelation', 'likesCountRelation')->get();
foreach ($users as $user) {
    echo $user->name;
    echo $user->likes_count;
    echo $user->fans_count;
}

但是如果你真的需要它,你应该重新思考。 1000行正常使用太多了。如果您将其用于导出目的,那很好,但如果您只在管理面板中显示它,则应该使用分页。

如果花费您很多时间,您应确保为fans列的likesuser_id表制作索引。它应该会加速你的查询。