for循环中由findOrFail引起的Laravel DB查询问题

时间:2019-02-20 12:50:02

标签: php database laravel eloquent execution-time

我的应用程序处理数千个数据库条目,并允许用户导出搜索结果列表的特定部分。

每个Entry都保存特定的文件,用户希望将其下载为压缩文件(例如zip)。效果很好,但是我很可能遇到了最大执行超时。我出于调试原因而尝试过,完全可以在我的PHP脚本中为PHP调整max_execution_time。两者都没有忽略该错误。

基本上我有两个问题:

  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 there a limit on checked checkboxes in PHP form POST?(也请阅读此特定的answer

1 个答案:

答案 0 :(得分:3)

您遇到了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确实可以。但是我们需要更多代码来进行分析。