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

Laravel共享全局搜索数据时产生大量重复查询问题排查

重复查询原因

  • 视图合成器使用*通配符匹配所有视图,每渲染一个视图(包括布局、子组件、嵌套视图)都会触发一次回调,页面如果涉及90个视图渲染,就会执行90次GlobalSearch查询逻辑。
  • GlobalSearch类未做结果缓存,每次调用all()方法都会重新执行SQL查询,没有复用已查询到的结果。
  • 冗余写法问题:View::share本身是全局共享视图变量的方法,不需要放在视图合成器中重复执行,进一步放大了重复调用的问题。

排查步骤

  1. 临时注释视图合成器代码,在单个控制器中手动调用一次GlobalSearch的all()方法,确认查询次数是否为1,验证是否为视图合成器重复触发导致的问题。
  2. 在propertyData()方法中添加日志,统计方法被调用的次数,确认调用次数和重复查询次数是否匹配,定位触发来源。
  3. 统计当前页面渲染的视图总数,确认视图数量是否等于90,验证通配符触发逻辑的猜想。

修复方案

1. 调整视图变量共享逻辑

移除通配符视图合成器,将全局变量共享逻辑改成仅在请求生命周期内执行一次:

public function boot()
{
    $this->app->resolving(function () {
        if (auth()->check() && optional(auth()->user())->currentTeam) {
            \View::share('SearchData', (new GlobalSearch(auth()->user()->currentTeam))->all());
        }
    });
}

如果不需要全局所有视图都用到SearchData,也可以指定视图合成器的匹配路径,不要用*通配符。

2. 为GlobalSearch增加查询缓存

在类中增加缓存属性,避免重复执行查询:

class GlobalSearch
{
    // 存储已查询的结果
    protected ?array $cachedResult = null;
    public $data;

    public function __construct(public Team $team){
        $this->data = $team->properties()->with(['leases', 'leases.tenant', 'leases.files', 'leases.invoices']);
    }


    protected function propertyData() : array
    {
        // 已有缓存直接返回
        if (!is_null($this->cachedResult)) {
            return $this->cachedResult;
        }
    
        $properties = $this->data->get();

        $this->cachedResult = $properties->map(function ($property) {
            $array['name'] = \Str::limit($property->address, 40);
            $array['url'] = route('properties.show', ['property' => $property]);
            
            return $array;
        })->toArray();  

        return $this->cachedResult;
    }


    public function all() : array
    {
       return $this->propertyData();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:30:02