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

Laravel查询优化:减少多条件多列数据检索的SQL请求次数

Laravel多Scope查询优化方案

当前实现的问题在于,每次调用单独的Scope都会触发一次独立的SQL查询,随着Scope数量增加,查询次数线性增长,直接导致响应延迟升高。优化核心是减少SQL查询次数,优先通过单次查询拉取数据后在应用层处理,或优化数据库查询逻辑。

方法一:单查询+集合筛选(推荐)

仅执行一次SQL获取当前客户的所有记录,再通过Laravel集合的filter方法完成分类筛选,彻底避免多查询问题。

步骤1:优化Model的Scope(解耦请求上下文)

将scopeSearch改为接收参数,避免直接依赖request(),提升复用性和可测试性:

public function scopeSearch($query, $customerId)
{
    return $query->where('Customer ID', $customerId);
}

// 保留原有Scope用于逻辑参考,也可直接在集合处理时编写判断逻辑
public function scopeFood($query)
{
    return $query->where('Food Column', 'LIKE', 'Fried%');
}

public function scopeDrink($query)
{
    return $query->where('Drink Column', 'LIKE', 'Juice%');
}

public function scopeAppetizer($query)
{
    return $query->where('Appetizer Column', 'LIKE', 'Hummus%');
}

步骤2:修改Controller逻辑

一次查询获取所有数据,再用集合筛选分类:

public function show()
{
    $customerId = request('customer_id');
    // 仅执行1次SQL查询
    $allRecords = Table::search($customerId)->orderBy('Date', 'DESC')->get();
    
    return view('menu', [
        'fried_food' => $allRecords->filter(fn($item) => str_starts_with($item->{'Food Column'}, 'Fried')),
        'juice_drink' => $allRecords->filter(fn($item) => str_starts_with($item->{'Drink Column'}, 'Juice')),
        'hummus_appetizer' => $allRecords->filter(fn($item) => str_starts_with($item->{'Appetizer Column'}, 'Hummus')),
    ]);
}

优势

  • 仅执行1次SQL查询,无论新增多少分类,查询次数都不会增加
  • Laravel集合操作效率极高,数据量不大时几乎无性能损耗
  • 代码逻辑清晰,易于维护和扩展

方法二:数据库层面聚合(适合超大数据量场景)

如果数据量极大,集合筛选带来的内存压力过高,可以通过一次查询用条件聚合完成统计,但此方法更适合仅需统计数据的场景(若需要具体记录,仍推荐方法一):

public function show()
{
    $customerId = request('customer_id');
    $stats = Table::search($customerId)
        ->selectRaw("
            COUNT(CASE WHEN `Food Column` LIKE 'Fried%' THEN 1 END) as fried_count,
            COUNT(CASE WHEN `Drink Column` LIKE 'Juice%' THEN 1 END) as juice_count,
            COUNT(CASE WHEN `Appetizer Column` LIKE 'Hummus%' THEN 1 END) as hummus_count
        ")
        ->first();
        
    return view('menu', compact('stats'));
}

额外优化建议

  • 给Customer ID、Food Column、Drink Column、Appetizer Column字段添加前缀索引(因为查询用的是LIKE 'XXX%'),进一步提升单查询的执行速度
  • 避免在Scope中直接依赖request(),始终通过参数传递上下文,符合Laravel最佳实践

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:30:24