You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化数据库查询以解决PDF导出超时问题

解决Laravel导出PDF超时问题(10K数据量)

问题描述

加载近10K条数据导出PDF时触发超时,报错信息:

Maximum Execution time off 60 seconds exceeded

原控制器代码

public function export(Request $request){
    $fotoOutcomes= new FotoOutcomeCollection(FotoOutcome::with('user','outcomeCategory','paymentMethod')->select('name','cost','date','pcs')->get());  
    $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
    return $pdf->download('Foto-Outcome.pdf');
}

原视图代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div className="overflow-x-auto">
    <table className="table table-zebra w-full">
        <thead>
            <tr>
                <th>No</th>
                <th>Name</th>
                <th>Date</th>
                <th>Pcs</th>
                <th>Cost</th>
            </tr>
        </thead>
        <tbody>
            @php $i=1 @endphp
            @foreach ($fotoOutcomes as $fotoOutcome)
            
            <tr>
                <th>{{$i}}</th>
                <td>{{$fotoOutcome->name}}</td>
                <td>{{$fotoOutcome->date}}</td>
                <td>{{$fotoOutcome->pcs}}</td>
                <td>{{$fotoOutcome->cost}}</td>
            </tr>
            @php $i++; @endphp
            @endforeach
        </tbody>
    </table>
</div>

优化方案

1. 移除未使用的关联预加载

视图中未用到user、outcomeCategory、paymentMethod关联数据,保留预加载会额外增加数据库查询开销,直接移除:

public function export(Request $request){
    $fotoOutcomes = new FotoOutcomeCollection(
        FotoOutcome::select('name','cost','date','pcs')->get()
    );  
    $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
    return $pdf->download('Foto-Outcome.pdf');
}

2. 用惰性加载减少内存占用

针对10K数据量,使用cursor()代替get()实现惰性加载,避免一次性加载所有数据到内存:

public function export(Request $request){
    $fotoOutcomes = new FotoOutcomeCollection(
        FotoOutcome::select('name','cost','date','pcs')->cursor()
    );  
    $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
    return $pdf->download('Foto-Outcome.pdf');
}

3. 优化视图计数逻辑

利用Blade自带的$loop变量替代手动计数,减少PHP代码执行开销:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div className="overflow-x-auto">
    <table className="table table-zebra w-full">
        <thead>
            <tr>
                <th>No</th>
                <th>Name</th>
                <th>Date</th>
                <th>Pcs</th>
                <th>Cost</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($fotoOutcomes as $fotoOutcome)
            <tr>
                <th>{{ $loop->iteration }}</th>
                <td>{{ $fotoOutcome->name }}</td>
                <td>{{ $fotoOutcome->date }}</td>
                <td>{{ $fotoOutcome->pcs }}</td>
                <td>{{ $fotoOutcome->cost }}</td>
            </tr>
            @endforeach
        </tbody>
    </table>
</div>

4. 临时延长执行时间(应急方案)

如果以上优化后仍超时,可临时延长脚本执行时间(不推荐作为长期解决方案):

public function export(Request $request){
    set_time_limit(120); // 延长至120秒
    
    $fotoOutcomes = new FotoOutcomeCollection(
        FotoOutcome::select('name','cost','date','pcs')->cursor()
    );  
    $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
    return $pdf->download('Foto-Outcome.pdf');
}

内容的提问来源于stack exchange,提问作者shinichirou ikebe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:44:55