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

Posted

技术标签:

【中文标题】在 laravel 中使用块或光标优化代码【英文标题】:Optimizing code with chunk or cursor in laravel 【发布时间】:2018-01-10 01:10:18 【问题描述】:

我在我的Laravel 5.4 应用程序中定义了Company 模型和Contact 模型,它们都有多对多的关系。因此,例如联系人模型有:

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

这对于小型数据集非常有效,但是在使用大量数据时它会失败(大约 10,000 个字段),我猜php memory fails 在涉及大型数据集时会加载。我正在浏览Laravel 文档以找出解决方案,并了解了chunk()cursor() 方法,有人可以指导我在这个问题上可以做些什么或有什么方法可以克服这个问题。

谢谢

【问题讨论】:

你熟悉 Chris Fidao 的“Laravel Performant”系列吗?他有一个关于 Laravel 中的 Database Chuncking 的视频,它准确地解释了你想要实现的内容。它也是免费的。 serversforhackers.com/laravel-perf/database-chunking 【参考方案1】:

我建议您测试这两种方法,以了解您的系统是否有些古怪。

块:

它将为您的查询“分页”,这样您就可以使用更少的内存。

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

`

public function getData() 
    Contact::chunk(1000, function ($contacts) 
        foreach ($contacts as $contact) 
            //rest of your code...
        
    );

`

光标:

您将使用 PHP 生成器逐一搜索您的查询项。

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

`

public function getData() 
    foreach (Contact::cursor() as $contact) 
        //rest of your code...
    

`

如需更详细的解释,请参阅此答案:What is the difference between laravel cursor and laravel chunk method?

有关性能测试,请参阅此帖子:https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fqiita.com%2Fryo511%2Fitems%2Febcd1c1b2ad5addc5c9d

【讨论】:

我不想要块中的数据,我想要我的数据库中存在的所有数据并在 foreach 循环中再运行 2 次查询每个数据,所以我使用了cursor(),但这对我没有帮助出来。 你分享的链接,我已经浏览过了,正如我在问题中提到的,我已经完成了背景调查。 我来自 c#:在列表中进行游标(linq'ing)是否意味着在您完成游标中的项目后,它会被释放,从而再次释放内存? 我不认为游标比块快,因为游标在往返过程中会花费很多时间

以上是关于在 laravel 中使用块或光标优化代码的主要内容,如果未能解决你的问题,请参考以下文章

laravel Repository 模式 优化代码

脚本 php artisan 优化处理使用 laravel 5.4 返回的 post-update-cmd 事件,错误代码为 1

Laravel - 如何优化 MIN - MAX - orderBy 查询?

如何优化使用 PHP 或 Mysql 或 Laravel 将 12K 的 JSON 插入数据库

Laravel中setAttribute和queryScope的用法

Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?