Optimización de consultas SQL

Los ORMs como Eloquent, a pesar de ser muy poderosos, pueden traer algunos problemas, uno de ellos es N+1 que ocurre típicamente cuando realizamos un ciclo y en cada vuelta del ciclo se ejecutan una o más consultas SQL adicionales. En esta lección veremos un repaso rápido sobre este problema y cómo solucionarlo.

Mira el código en GitHub: actual, resultado, comparación.

Es imposible crear un curso de optimización con Eloquent sin abordar el problema de N+1, pero puesto que este tema ya lo hemos visto con calma en varios videotutoriales como:

Voy simplemente a dar un repaso rápido del problema:

Cuando se ejecuta la línea $products = \App\Product::all();, Eloquent realiza la siguiente consulta para traer todos los productos de la base de datos:

#
SELECT * FROM `products`

Nota que no está trayendo las categorías a pesar de que éstas son mostradas en la lista con:

@forelse($products as $product)
    <a href="{{ url('productos/categoria/'.$product->category->slug) }}">
        {{ $product->category->title }}
    </a>
@empty
    <!-- // -->
@endforelse

Aquí radica el problema, Eloquent hace una consulta en cada vuelta del ciclo para traer una categoría cada vez:

#
SELECT * FROM `product_categories` WHERE `product_categories`.`id` = '1' LIMIT 1

Eager loading o carga previa con Eloquent

La solución a este problema es utilizar una técnica conocida como Eager Loading o Carga Previa:

<?php
// routes/web.php
$products = \App\Product::with('category')->get();

Esto reducirá la cantidad de consultas SQL ejecutadas por el ORM a dos:

#
SELECT * FROM `products`

SELECT * FROM `product_categories` WHERE `product_categories`.`id` in (1, 2, 3)

Una consulta para traer todos los productos y otra para obtener las categorías de productos requeridas por dichos productos (he reducido la cantidad de IDs de categorías para simplificar el código).

Al reducir la cantidad de consultas ejecutadas por el ORM obtendremos un tiempo de respuesta más rápido y, por lo tanto, con esto completamos la primera optimización.

No olvides revisar los enlaces debajo del video para aprender más sobre esta técnica y cómo detectar problemas de N+1.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Tip de optimización con Eloquent #1: Verifica las consultas ejecutadas Lección siguiente Tip de optimización con Eloquent #3: Selecciona columnas específicas