如何加快这个Eloquent查询的速度?

时间:2016-10-24 21:04:44

标签: php laravel laravel-5 eloquent

以下查询正在检索大型数据集(~25k行)。它运行得非常慢,我想知道如何加快速度:

$jobs = Job::whereArchived(true)->get();

    foreach ($jobs AS $job)
    {
        $rows[] = [
            "<a href='/admin/projects/jobs/$job->id'>{$job->name}</a>",
            $job->start_date ? $job->start_date : "Not Specified",
            $job->end_date ? $job->end_date : "Not Specified", 
            $job->agent ? $job->agent->name : "Unassigned",
            $job->status ? $job->status : "Not Specified"

        ];
    }
echo Html::table()
    ->head($headers)
    ->body($rows)
    ->datatable();

此特定查询/结果至少需要60秒才能完成。我怎样才能加快速度呢?

2 个答案:

答案 0 :(得分:1)

您需要急切加载相关的代理模型,否则对于每个作业记录,当您尝试访问 $ job-&gt; agent <时,会运行其他查询/强>

替换

$jobs = Job::whereArchived(true)->get();

$jobs = Job::with('agent')->whereArchived(true)->get();

您应该会看到查询效果的显着改善。

如果逻辑仍然需要太长时间以满足您的需求,您可能希望完全跳过Eloquent层,这是您的查询可能需要花费大量时间才能执行的另一个原因是您使用Eloquent获取数据model - 因为对于从数据库中提取的每一行,都需要创建类 Job 的对象。

如果您将数据作为数组获取并跳过从中创建对象的逻辑,则处理大量数据会更有效。您可以使用数据库外观

获取数据
$jobs = DB::table('jobs')->where('archived', '=', true)->join('agents', 'jobs.agent_id', '=', 'agents.id')->get();

这也应该会显着提升性能。

另一个原因是您从数据库中获取所有可用列,而不仅仅是您需要的列,这会增加内存使用量以及将数据从数据库传输到应用程序所需的时间。您可以通过指定您需要的列列表来解决这个问题,以便只加载这些列:

$jobs = Job::with('agent')->whereArchived(true)
  ->get(['name', 'start_date', 'end_date', 'status']);

$jobs = DB::table('jobs')->where('archived', '=', true)
  ->join('agents', 'jobs.agent_id', '=', 'agents.id')
  ->get(['name', 'start_date', 'end_date', 'status']);

最后,想想你是否真的需要一次显示所有记录。通常不需要,并且可以显示分页结果。您可以在文档中找到有关分页的更多信息以及一些示例:https://laravel.com/docs/5.3/pagination

答案 1 :(得分:1)

您可以使用其他答案中指定的with()函数来加载相关模型,但在单个查询中获取25k结果并不是一个好方法。分页是这种情况的理想选择,您可以使用ajax来获取其余页面。 如果分页不是您的选项,那么请尝试将列归档&#39;归档&#39;并使用预先加载来获取结果。它将显着提高查询性能。