Wednesday, March 8, 2017

Performance issue when json encoding nested relationships in Laravel

I'm fetching data from a database using Laravel's (5.2) Eloquent ORM like so:

$orders = Order::with([
    'customer',
    'items',
    'items.product',
    'items.product.shop' => function ($query) {
        $query->select(['id', 'title']);
    }
])->get();

Note: the reason why a shop is not tied to a single order is that orders may contain items from multiple shops. Each item references the ordered product, which in turn has a reference to the shop it belongs to.

This works fine, however, when I want to return the result to a view and render it there, it takes a long time to json_encode it.

I confirmed that json_encode is indeed the bottleneck, if I just execute the query and immediately die afterwards, the response is almost instant. However, if I do a $orders->toJson() (or json_encode($orders)) after the query, I experience the same delay in response as with returning the result to the view.

Apparently the problem lies in the (too deeply?) nested property of items.product.shop, if I remove that, the call to json_encode doesn't induce any performance issues.

Here's a sample output of a single order:

{
  "id": 71,
  "total_sum": "5.88",
  "customer": {
    "id": 68,
    "first_name": "One Large",
    "last_name": "Men's"
  },
  "items": [
    {
      "id": 105,
      "quantity": "1",
      "price_single": "1.2",
      "price_total": "1.2",
      "color_id": "6",
      "size_id": "5",
      "order_id": "71",
      "product": {
        "id": 149,
        "name": "Men's",
        "shop": {
          "id": 109,
          "title": "general test"
        }
      }
    }
  ]
}



via falloutghst

Advertisement