在laravel中使用块或光标优化代码

在laravel中使用块或光标优化代码,laravel,eloquent,laravel-5.4,laravel-eloquent,Laravel,Eloquent,Laravel 5.4,Laravel Eloquent,我在我的Laravel 5.4应用程序中定义了公司模型和联系人模型,两者都有多对多关系。例如,联系人模型具有: public function company() { return $this ->belongsToMany('App\Company', 'company_contact','contact_id', 'company_id')->withTimestamps(); } 现在我有了一个数据集,我想从中提取所有联系人数据,并获取公司详细信息,所

我在我的
Laravel 5.4
应用程序中定义了
公司
模型和
联系人
模型,两者都有多对多关系。例如,联系人模型具有:

public function company()
{
    return $this
        ->belongsToMany('App\Company', 'company_contact','contact_id', 'company_id')->withTimestamps();
}
现在我有了一个数据集,我想从中提取所有联系人数据,并获取公司详细信息,所以我使用了:

public function getData()
{
    $contacts = Contact::all();
    foreach($contacts as $contact)
    {
        $getCompany = $contact->company()->withPivot('created_at')->orderBy('pivot_created_at', 'desc')->first();
        $getCompany->contacts = Company::find($getCompany->id)->contacts;
        $contact->company = $getCompany;
        $contact->companies_interested = json_decode($contact->companies_interested);
        $companies = [];
        if($contact->companies_interested)
        {
            foreach($contact->companies_interested as $companiesInterested)
            {
                $getCompany = Company::withTrashed()->find($companiesInterested);
                $companies[] = array(
                    'value' => $getCompany->id,
                    'label' => $getCompany->name
                );
            }
            $contact->companies_interested = json_encode($companies);
        }
    }
    return response()->json([
        'model' => $contacts
    ], 200);
}
这对于小数据集非常有效,但在使用大量数据时(大约10000个字段),我猜
php内存在加载大数据集时会失败。我正在通过
Laravel
文档来找到解决方案,并了解了
chunk()
cursor()
方法,有人可以指导我在这个问题上可以做些什么,或者可以用什么方法来克服这个问题


谢谢

我建议您测试这两种方法,以了解系统的一些古怪之处

区块:

它将“分页”您的查询,这样您使用更少的内存

  • 使用更少的内存
  • 这需要更长的时间
`

`

光标:

您将使用PHP生成器逐个搜索查询项

  • 它花费的时间更少
  • 使用更多内存
`

`

有关更详细的解释,请参见以下答案:


有关性能测试的信息,请参见以下帖子:

您熟悉Chris Fidao的“Laravel Performant”系列吗?他在Laravel为数据库Chunking制作了一个视频,准确地解释了您试图实现的内容。它也是免费的。我不希望数据成堆,我希望数据库中的所有数据都存在,并在foreach循环中对每个数据再运行两次查询,所以我使用了
cursor()
,但这对我没有帮助。你共享的链接,我已经看过了,正如我在问题中提到的,我已经做了背景检查。我来自c#:不诅咒(linq'ing)列表意味着在完成游标中的项目后,它将被释放,从而再次释放内存?我不认为游标比chunk快,因为游标在往返过程中会花费很多时间
public function getData() {
    Contact::chunk(1000, function ($contacts) {
        foreach ($contacts as $contact) {
            //rest of your code...
        }
    });
}
public function getData() {
    foreach (Contact::cursor() as $contact) {
        //rest of your code...
    }
}