使用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
相关产品推荐
相关产品推荐

