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

使用DB查询替代Eloquent查询优化Web应用数据加载速度

数据库查询优化方案(替代Eloquent提升加载速度)

核心优化点及实现代码

针对你代码中存在的重复查询、冗余数据加载、N+1查询等问题,以下是基于DB门面的优化实现:


1. 合并Order表统计查询(减少8次查询为1次)

原代码中每次统计单独查询Order表,现在通过一次分组查询获取所有统计数据:

// 一次性获取所有订单类型的统计
$orderStats = DB::table('orders')
    ->select('sname', DB::raw('count(*) as total'))
    ->whereIn('sname', [
        'Soil Testing', 
        'Produce Collection', 
        'Farmer Registration', 
        'Nyota Beans', 
        'Pruning Shears', 
        'Avocado Harvesting Secateurs', 
        'FCM Traps & Housing', 
        'Fruit Fly Traps and Housing'
    ])
    ->where(function($query) {
        // 仅对"Avocado Harvesting Secateurs"取消status=0的限制
        $query->where('status', 0)
              ->orWhere('sname', 'Avocado Harvesting Secateurs');
    })
    ->groupBy('sname')
    ->pluck('total', 'sname');

// 从统计结果中提取各变量
$soil = $orderStats->get('Soil Testing', 0);
$collection = $orderStats->get('Produce Collection', 0);
$registration = $orderStats->get('Farmer Registration', 0);
$nyota = $orderStats->get('Nyota Beans', 0);
$shears = $orderStats->get('Pruning Shears', 0);
$secateurs = $orderStats->get('Avocado Harvesting Secateurs', 0);
$traps = $orderStats->get('FCM Traps & Housing', 0);
$flytraps = $orderStats->get('Fruit Fly Traps and Housing', 0);

2. 优化Fields列表查询(只加载视图需要的字段+分页)

原代码加载Field全量数据并预加载关联,现在通过JOIN直接获取关联字段,只选择视图用到的列,并添加分页:

// 仅查询视图需要的字段,通过JOIN获取农户信息,避免N+1查询
$fields = DB::table('fields')
    ->select(
        'fields.id',
        'fields.fieldname',
        'fields.crop',
        'fields.farmblocksno',
        'farmers.name as farmer_name',  // 假设Farmer表的名字字段是name
        'farmers.idno as farmer_idno'   // 假设Farmer表的身份证号字段是idno
    )
    ->join('farmers', 'fields.farmer_id', '=', 'farmers.id') // 根据实际外键调整
    ->latest('fields.created_at')
    ->paginate(20); // 每页20条,可根据需求调整

注意:如果farmer_name和farmer_idno本身就是Field表的字段,可去掉JOIN,直接选择对应字段即可。

3. 简化Crop数据处理(直接查询出所需格式)

原代码循环处理Crop数据,现在直接通过查询构造目标数组:

// 直接查询出图表需要的格式,无需循环转换
$data = DB::table('crop')
    ->select('crop as label', 'expectedvolume as y')
    ->get()
    ->toArray();

4. 移除冗余查询(如果视图未用到)

检查视图代码,发现未使用$farmers和$offers数据,可直接删除这两个查询:

// 原代码中冗余的查询,可删除
// $farmers = Farmer::with('fields')->latest()->get();
// $offers = Offer::latest()->get();

完整优化后的Controller代码

public function farmers()
{
    // 1. 订单统计优化
    $orderStats = DB::table('orders')
        ->select('sname', DB::raw('count(*) as total'))
        ->whereIn('sname', [
            'Soil Testing', 
            'Produce Collection', 
            'Farmer Registration', 
            'Nyota Beans', 
            'Pruning Shears', 
            'Avocado Harvesting Secateurs', 
            'FCM Traps & Housing', 
            'Fruit Fly Traps and Housing'
        ])
        ->where(function($query) {
            $query->where('status', 0)
                  ->orWhere('sname', 'Avocado Harvesting Secateurs');
        })
        ->groupBy('sname')
        ->pluck('total', 'sname');

    // 提取统计值
    $soil = $orderStats->get('Soil Testing', 0);
    $collection = $orderStats->get('Produce Collection', 0);
    $registration = $orderStats->get('Farmer Registration', 0);
    $nyota = $orderStats->get('Nyota Beans', 0);
    $shears = $orderStats->get('Pruning Shears', 0);
    $secateurs = $orderStats->get('Avocado Harvesting Secateurs', 0);
    $traps = $orderStats->get('FCM Traps & Housing', 0);
    $flytraps = $orderStats->get('Fruit Fly Traps and Housing', 0);

    // 2. 农田列表优化
    $fields = DB::table('fields')
        ->select(
            'fields.id',
            'fields.fieldname',
            'fields.crop',
            'fields.farmblocksno',
            'farmers.name as farmer_name',
            'farmers.idno as farmer_idno'
        )
        ->join('farmers', 'fields.farmer_id', '=', 'farmers.id')
        ->latest('fields.created_at')
        ->paginate(20);

    // 3. 作物数据优化
    $data = DB::table('crop')
        ->select('crop as label', 'expectedvolume as y')
        ->get()
        ->toArray();

    // 传递数据到视图(移除冗余的farmers和offers)
    return view('admins.farmers', [
        'data' => $data,
        'collection' => $collection,
        'registration' => $registration,
        'fields' => $fields,
        'soil' => $soil,
        'nyota' => $nyota,
        'shears' => $shears,
        'secateurs' => $secateurs,
        'traps' => $traps,
        'flytraps' => $flytraps
    ]);
}

额外优化建议

  • 给orders.sname、orders.status、fields.farmer_id、farmers.id这些查询中用到的字段添加数据库索引,进一步提升查询速度。
  • 如果分页后前端需要总条数,Laravel的分页对象已经包含,可直接在视图中使用{{ $fields->total() }}。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:45:41