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

优化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:53:09