Проблемы с запросом Laravel DB, вызванные findOrFail в цикле for

Мое приложение обрабатывает тысячи записей в базе данных и позволяет пользователю экспортировать определенную часть списка результатов поиска.

Каждый Entry содержит определенные файлы, и пользователь хочет загрузить их в сжатом файле (например, zip). Это работает нормально, но я, скорее всего, столкнулся с максимальным временем ожидания выполнения. Я пытался по причинам отладки просто настроить max_execution_time для PHP вообще и в моем php-скрипте. Оба не пропустили ошибку.

В основном у меня есть два вопроса:

  1. Как правильно проанализировать проблему? (Связано ли это с максимальным временем выполнения)
  2. Как опустить максимальные тайм-ауты выполнения? (Скорее всего это так, потому что с меньшим количеством запросов он работает просто отлично)

Пример кода:

public function export(Requests\ExportRequest $request)
{
    $input = $request->all();

    foreach ($input['entries'] as $id) {
        $entry = Entry::findOrFail($id);
    }
}

ИЗМЕНИТЬ:

К вашему сведению, проблема была не в max_execution_time, даже если это значительно сократило количество SQL-запросов. Проблема была вызвана ограничением max_input_vars. Целевые записи были проверены в форме и отправлены в функцию export(). У каждого флажка было name=entries[], из-за чего каждая запись имела отдельное входное значение. Подробнее об этой проблеме можно прочитать здесь: Is есть ли ограничение на установленные флажки в PHP-форме POST? (подумайте также о том, чтобы прочитать этот конкретный ответ)


person Michael Czechowski    schedule 20.02.2019    source источник
comment
Вы можете включить параметр mysql, чтобы регистрировать медленные запросы и анализировать их позже, и вы можете использовать очередь для создания этого, а затем отправлять его пользователю, когда он будет готов.   -  person thefallen    schedule 20.02.2019
comment
ммм, обычно я использую метод чанка из красноречивого, чтобы избежать максимального времени выполнения.   -  person pinoyCoder    schedule 20.02.2019


Ответы (1)


Вы столкнулись с проблемой N+1: вы выполняете отдельный запрос для каждой записи, которую хотите получить. Вы можете получить все записи сразу, написав соответствующий запрос. Я точно не знаю, что происходит после опубликованного вами кода, поскольку опубликованный код ничего не делает. Но выполнение 1000 отдельных запросов на несколько порядков медленнее, чем выполнение 1 большого запроса.

public function export(Requests\ExportRequest $request)
{
    $input = $request->all();

    $allEntries = Entry::whereIn('entry_id', $input['entries'])->get();

    // All entries is a Collection with all the queried entries in it
}

Мое эмпирическое правило состоит в том, что всякий раз, когда max_execution_time вступает в игру, я принял плохое архитектурное решение. Может быть, мое решение решает проблему, а может быть, решение @TheFallen. Но нам нужно больше кода, чтобы проанализировать это.

person Loek    schedule 20.02.2019
comment
Хорошо, это помогло сократить обработку запросов, но не решило мою проблему. Это действительно помогло отлаживать, поэтому решает мой вопрос. Следующим моментом может быть то, что я использую POST для обработки входящих идентификаторов записей. Существует ли максимальная полезная нагрузка параметров запроса POST? - person Michael Czechowski; 20.02.2019
comment
Обычный максимальный размер запроса GET составляет 8 килобайт, но браузеры могут мешать (например, Safari разрешает только 2 килобайта). Я не знаю, сколько параметров вы обычно обрабатываете, но 2 КБ должно быть более чем достаточно. Проблема, вероятно, в том, что заархивирование записей занимает много времени (архивирование 6 файлов размером около 10 МБ занимает много времени, вы можете ускорить это, только задействовав больше ЦП). Может быть идея разгрузить весь процесс в очередь и отправить пользователю электронное письмо, когда его файлы будут готовы..? Тем не менее, нам нужно больше кода, чтобы правильно его проанализировать. - person Loek; 20.02.2019
comment
Извините, это был POST-запрос. Я отредактировал свой комментарий. - person Michael Czechowski; 20.02.2019
comment
Я обсужу это в другом вопросе, потому что это не должно иметь отношения к обработке sql. Спасибо за помощь! - person Michael Czechowski; 20.02.2019
comment
Даже если удалить все заархивированные файлы, код даже не будет выполняться. Итак, я предполагаю, что нужно искать уменьшение полезной нагрузки POST-запроса. - person Michael Czechowski; 20.02.2019