Home > Back-end >  How to improve eloquent nested foreach performance
How to improve eloquent nested foreach performance

Time:03-13

How can I improve the performance of a query with the following characteristics (this is a simulation to exemplify):

public function getData() 
{
    $itens = Item::orderBy('id_item', 'DESC')->get();

    foreach($itens as $item){
        $item->games = $item->games()->get();

        foreach( $item->games as $player){
            $item->players = $player->players()->get();
        }
    }
    
    return response()->json(['success'=>true, 'itens'=>$itens]);
}

In my real case, the foreach returns a lot of data with performance problems;

The Waiting (TTFB), that is, the time the browser is waiting for the first byte of a response, takes almost 27s

CodePudding user response:

class Item extends Model{
  // ...

  public function games(){
    return this->hasMany(Game::class);
  }

  public function players(){
    return this->hasManyThrough(Player::class ,Game::class);
  }
}
public function getData() 
{
    $itens = Item::orderBy('id_item', 'DESC')->with('games','players')->get();
    
    return response()->json(['success'=>true, 'itens'=>$itens]);
}

That will result in 3 queries and the output will be like:

[
  // item 0 ...
  [
    // item data
    [
      // games
    ],
    [
      // players
    ]
  ],

  // other items
]

CodePudding user response:

Here you go

public function getData() 
{
    $items = Item::with('games.players')->orderBy('id_item', 'DESC')->get();
    
    return response()->json(['success'=>true, 'items'=>$items]);
}

CodePudding user response:

Code based solutions:

  • Looping on array is around 2 times cheaper than looping on List.
  • A 'for' loop is much faster than 'foreach'

a other solutio is:

  • Filtering unnecessary parts for running the loop
  • Related