【问题标题】:Laravel: improve performance when having multiple eager loading queriesLaravel:在有多个急切加载查询时提高性能
【发布时间】:2019-04-10 11:04:34
【问题描述】:

我正在尝试提高我的 laravel 应用程序的性能。通过删除视图中的延迟加载,我已经能够将查询量从 68 个减少到 20 个。

但是,使用预加载,仍然有 20 个查询几乎完成相同的操作。我的代码如下所示:

$products = [
        'latest' => Product::with('vehicle', 'brand', 'type', 'photos')->withoutGlobalScope(ProductScope::class)->latest()->take(5)->get(),
        'most_viewed' => Product::with('vehicle', 'brand', 'type', 'photos')->withoutGlobalScope(ProductScope::class)->mostViewed()->take(5)->get(),
        'nearest' => Product::with('vehicle', 'brand', 'type', 'photos')->withoutGlobalScope(ProductScope::class)->nearest($address)->take(5)->get(),
    ];

这会产生 15 个查询(每个 5 个),因为每次还会再次查询关系。是否可以将这些查询组合在一起,使其可能减少到 7 个查询而不是 15 个?

【问题讨论】:

  • 你使用的是什么版本的 Laravel?
  • 对不起,忘了说,我用的是 Laravel 5.8

标签: laravel performance eloquent eager-loading


【解决方案1】:

由于不同的集合应该通过引用传递,您应该能够将它们组合成一个 Eloquent 集合,然后使用Lazy Eager Loading

$products = [
    'latest'      => Product::withoutGlobalScope(ProductScope::class)->latest()->take(5)->get(),
    'most_viewed' => Product::withoutGlobalScope(ProductScope::class)->mostViewed()->take(5)->get(),
    'nearest'     => Product::withoutGlobalScope(ProductScope::class)->nearest($address)->take(5)->get(),
];

//Merge the different Product collections into one for the lazy eager loading 

$collection = new \Illuminate\Database\Eloquent\Collection();

foreach ($products as $items) {
    foreach ($items as $model) {
        $collection->push($model);
    }
}

$collection->load('vehicle', 'brand', 'type', 'photos');

//$products should now contain the different collections but with the additional relationships.

$products 数组中的原始集合现在应该已经加载了所有关系,但它应该只执行了 4 次查询,而不是 12 次。

【讨论】:

  • 您的解决方案部分有效。我可以看到查询量减少了。但是,如果同一产品出现在多个集合中,则只有最后一个产品具有关系。
  • @LexdeWilligen 啊,是的,merge 使用模型中的密钥,因此它只会将其中一个加载到集合中。我更新了我的答案,应该会给你你想要的。
  • 嗯,你又猜对了一半。所有模型都加载得很好,但是,出于某种原因,most_viewednearest 中的项目也添加到了latest。如果我更改订单,项目将被推送到第一个 $products 数组项目。
  • @LexdeWilligen 我已经更新了我的答案,只使用一个新的 Eloquent Collection 实例,它应该可以解决最后一个问题。
猜你喜欢
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 2014-06-12
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多