Ограничение памяти Laravel 3 и MYSQL

У меня проблема с запросом в Laravel 3.

Моя таблица пока что насчитывает всего лишь 90 000 строк, что не так уж много по стандартам MYSQL. Честно говоря, я только ожидал столкнуться с этой проблемой где-то около 10-20 миллионов строк.

Но в любом случае.... Я использую эту таблицу для статистики, и кажется, что я не могу запросить всю таблицу через laravel. По мере достижения лимита памяти.

С помощью...

public function action_viewcalls(){

$calls = Call::get();
var_dump($calls);

}

Ничего не возвращает Просто пустая страница.

Если я ограничу его только идентификатором или Phone_no

 $calls = Call::get(array('id');
var_dump($calls);

Затем я могу получить все строки и пройти по ним циклом. Но если я попытаюсь получить более 3 столбцов из пяти в этой таблице. Я ничего не возвращаю и не могу зациклить результаты.

Я даже не получаю сообщение об ошибке или что-либо об ограничениях памяти MYSQL.

Я просто получил пустую белую страницу. Даже если я...

public function action_viewcalls(){

$calls = DB::query("SELECT * FROM calls");
var_dump($calls);

}

Есть идеи??? Не похоже, что 90 000 строк должны вызывать проблемы. Что может быть причиной этого?

Спасибо

1 ответ

Как и ceejayoz, упомянутый в комментариях, вероятно, PHP достиг предела памяти.

Это происходит потому, что когда вы звоните get() вы просите Laravel вернуть вам ВСЕ строки сразу. Строки в 90 тыс., В зависимости от того, что в них содержится, могут занимать много памяти за один раз.

Я столкнулся с этой проблемой сегодня, с количеством строк менее 90 КБ, используя Eloquent ORM и готовые отношения загрузки для набора данных < 1000 записей.

Некоторые возможные решения для обработки и / или отображения всех ваших записей:

  • Одна из идей Laravel-y: используйте разбиение на страницы, чтобы обрабатывать и отображать только определенные части данных одновременно. Я не уверен, что это доступно в Laravel 3.x, но в Laravel 4 это есть.
  • Используйте цикл, который использует take() а также skip() ( Документы здесь внизу раздела) для перебора большого набора данных. Тем не менее, вам также необходимо знать об ограничении времени выполнения PHP, так как это может вызвать проблемы при использовании этого решения.

    $take = 100; // adjust this however you choose
    $counter = 0; // used to skip over the ones you've already processed
    while($rows = Call::take($take)->skip($counter)->get())
    {
        // process these rows
        // ...
        $counter += $take;
    }
    
  • Другой вариант - просто сначала захватить идентификаторы и загрузить соответствующие записи по мере необходимости. Например:

    $ids = Call::get(array('id'));
    foreach($ids as $id)
    {
        // grab the actual record...
        $call = Call::find($id);
        if($call)
        {
            // do stuff with this one
        }
    }
    

    Это по-прежнему связано с проблемой максимального времени выполнения, поскольку обработка такого количества записей при загрузке одной страницы, вероятно, превысит ее, независимо от того, что вы делаете.

  • Вы также можете увеличить максимальную память PHP, но это не всегда возможно в производственной среде, в зависимости от вашего хостинг-провайдера.
  • Мое предложение: если Pagination Laravel не делает то, что вы хотите (как в моем случае), вы можете создать собственное решение для разбивки на страницы, используя метод take-skip, описанный выше, но используя динамические ссылки, которые перезагружают страницу со значениями take и skip в URI. Я предполагаю, что вы планируете показать некоторую часть этой информации пользователю на странице. Это имеет преимущество в том, что не вызывает проблем с максимальным временем выполнения PHP или ограничением памяти. Сделано правильно, это может хорошо работать и хорошо выглядеть. Вы могли бы даже просто использовать <select> с onChange обработчик, который перезагружает часть страницы, используя ajax, если вы действительно амбициозны.
Другие вопросы по тегам