优化Laravel命令:减少SQL查询,提升多仓库处理性能
Laravel ReportPendingPackages 命令性能优化方案
核心优化思路
直接移除循环遍历公司的逻辑,通过数据库层面的批量查询+批量插入完成所有数据处理,彻底减少SQL交互次数;利用分组查询直接按company_id或company_mara聚合数据,一步到位插入目标表。
具体实现方案
1. 用 INSERT ... SELECT 完成批量插入(最优方案)
直接通过数据库原生语句完成查询+插入,无需PHP中转数据,性能提升最明显。
场景1:插入所有待处理包裹明细(按company_id拆分)
// 在命令的handle方法中替换原有循环逻辑 DB::beginTransaction(); try { // 先清空报表表(按需选择,若需保留历史则跳过) DB::table('report_pending_packages')->truncate(); // 单条SQL完成所有公司数据的查询+插入 DB::statement(" INSERT INTO report_pending_packages (company_id, package_id, status, created_at, updated_at) SELECT p.company_id, p.id AS package_id, p.status, NOW(), NOW() FROM packages p WHERE p.status = 'pending' "); DB::commit(); } catch (\Exception $e) { DB::rollBack(); throw $e; }
场景2:按company_id分组统计待处理数量
如果报表只需要各公司的汇总数据,直接分组聚合:
DB::statement(" INSERT INTO report_pending_packages (company_id, pending_count, created_at, updated_at) SELECT p.company_id, COUNT(p.id) AS pending_count, NOW(), NOW() FROM packages p WHERE p.status = 'pending' GROUP BY p.company_id ");
场景3:按company_mara分组处理
若需关联company_mara表按关联维度分组:
DB::statement(" INSERT INTO report_pending_packages (company_id, mara_id, pending_count, created_at, updated_at) SELECT cm.company_id, cm.mara_id, COUNT(p.id) AS pending_count, NOW(), NOW() FROM packages p JOIN company_mara cm ON p.company_id = cm.company_id WHERE p.status = 'pending' GROUP BY cm.company_id, cm.mara_id ");
2. 索引优化(必做)
给packages表添加联合索引,加速查询和分组操作:
CREATE INDEX idx_packages_company_status ON packages (company_id, status);
如果关联company_mara,也给关联字段添加索引:
CREATE INDEX idx_company_mara_company ON company_mara (company_id);
3. Laravel风格的替代写法(避免原生SQL)
如果偏好Eloquent语法,使用insertUsing方法:
DB::table('report_pending_packages')->insertUsing( ['company_id', 'package_id', 'created_at', 'updated_at'], function ($query) { $query->select( 'p.company_id', 'p.id AS package_id', DB::raw('NOW()'), DB::raw('NOW()') )->from('packages as p') ->where('p.status', 'pending'); } );
关键优势
- 彻底消除循环公司带来的N次SQL查询,将操作压缩为1-2次数据库交互
- 利用数据库原生的批量操作,性能远高于PHP循环插入
- 分组逻辑直接在数据库层面完成,避免PHP内存占用过高
内容的提问来源于stack exchange,提问作者Edin Osmic
相关产品推荐
相关产品推荐

