Оптимизация кода с помощью чанка или курсора в laravel

У меня есть модель Company и модель Contact, определенные в моем приложении 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);
}

Это отлично работает для небольшого набора данных, но при использовании большого количества данных происходит сбой (около 10 000 полей), я думаю, php memory fails загружать, когда речь идет о большом наборе данных. Я просматривал документы Laravel, чтобы найти решение, и узнал о методах chunk() и cursor(). Может ли кто-нибудь подсказать мне, что можно сделать в этой проблеме или какой подход можно преодолеть.

Спасибо


person Nitish Kumar    schedule 02.08.2017    source источник
comment
Вы знакомы с серией Laravel Performant Криса Фидао? У него есть видео о фрагментировании базы данных в Laravel, в котором объясняется, что именно вы пытаетесь реализовать. Это также бесплатно. serversforhackers.com/laravel-perf/database-chunking   -  person Victor    schedule 02.08.2017


Ответы (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...
    }
}

`

Для более подробного объяснения см. этот ответ: В чем разница между курсором laravel и методом фрагмента laravel?

Для тестирования производительности см. этот пост: https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fqiita.com%2Fryo511.%2Fitems%2Febcd1c1b2ad5addc5c9d

person Jean Marcos    schedule 02.08.2017
comment
Мне не нужны данные в кусках, я хочу, чтобы все данные присутствовали в моей базе данных и выполняли еще 2 запроса для каждого данных в цикле foreach, поэтому я использовал cursor(), но это мне не помогает. - person Nitish Kumar; 03.08.2017
comment
Ссылку, которой вы поделились, я уже прошел через нее, как я уже упоминал в вопросе, я уже проверил биографические данные. - person Nitish Kumar; 03.08.2017
comment
Я пришел из С#: не означает ли курсор (связывание) списка, что после того, как вы закончите с элементом в курсоре, он будет удален и, таким образом, снова освободит память? - person Joel Harkes; 21.02.2019
comment
Я не думаю, что курсор быстрее, чем кусок, потому что курсор займет много времени в оба конца - person Veshraj Joshi; 10.07.2020