Probablemente, si estás leyendo esto, has encontrado el problema N+1 durante el desarrollo de Django o lo has encontrado al menos una vez en el pasado. Debido a este problema, la velocidad de carga de la página se vuelve lenta y es probable que hayas descubierto select_related y prefetch_related mientras buscabas una solución.

¡Primero que nada, bienvenido a mi blog! 🎉 Si lees este artículo hasta el final, seguro que podrás aprender cómo resolver el problema N+1 de manera efectiva.

Si no estás completamente seguro del concepto de problema N+1, te recomiendo que leas el siguiente artículo primero.

¿Qué es el problema N+1 en Django ORM? ¿Por qué ocurre?

🔍 Dos maneras de resolver el problema N+1 en Django

En Django ORM, puedes resolver el problema N+1 utilizando dos funciones: select_related y prefetch_related. Sin embargo, dado que estas dos funciones operan de manera diferente, es importante entender exactamente cuándo usar cada una.

📌 Principios comunes de select_related y prefetch_related

El principio común clave entre estos dos métodos es que traen todos los campos necesarios en una sola consulta a la base de datos y permiten usar los datos obtenidos de manera eficiente en Django.

Por ejemplo, imagina que vas a un gran supermercado para hacer un pastel y compras todos los ingredientes necesarios, como harina, crema batida y frutas, de una sola vez. Cuando llegas a casa y comienzas a cocinar, ya tienes todos los ingredientes listos, por lo que puedes comenzar a cocinar de inmediato.

Pero, ¿qué pasaría si tuvieras que ir a comprar los ingredientes uno por uno? Compras la harina y cuando vuelves a casa y comienzas a amasar, te das cuenta de que te falta la crema batida y tienes que volver al supermercado; compras la crema batida y ahora no tienes frutas, así que necesitas ir otra vez al mercado. ¿No sería esto extremadamente lento para cocinar?

De esta manera, la preparación de la comida tomaría mucho tiempo. En Django ORM, select_related y prefetch_related ayudan a prevenir estas llamadas de datos ineficientes, permitiendo traer los datos necesarios con una única consulta a la base de datos para procesarlos rápidamente.

Select Related vs Prefetch Related en Django ORM

✅ 1. select_related – Carga inmediata utilizando SQL JOIN

Utilizado en relaciones ForeignKey (1:N)

  • Trae los datos utilizando SQL JOIN en una sola consulta
  • No hay solicitudes adicionales a la base de datos porque se obtiene inmediatamente el objeto relacionado

📌 Ejemplo de uso de select_related

authors = Author.objects.select_related('post_set').all()

🧐 SQL ejecutado cuando select_related no se aplica

SELECT * FROM author;
SELECT * FROM post WHERE author_id = 1;
SELECT * FROM post WHERE author_id = 2;
...

🚀 SQL ejecutado cuando se aplica select_related

SELECT * FROM author INNER JOIN post ON author.id = post.author_id;

✅ 2. prefetch_related – Carga previa utilizando consultas individuales

Utilizado en relaciones ManyToMany y Reverse ForeignKey

  • Django ejecuta consultas individuales y luego optimiza y conecta los datos en Python
  • Como no utiliza SQL JOIN, puede ser más ventajoso al manejar una gran cantidad de datos

📌 Ejemplo de uso de prefetch_related

authors = Author.objects.prefetch_related('post_set').all()

🧐 SQL ejecutado después de aplicar prefetch_related

SELECT * FROM author;
SELECT * FROM post WHERE author_id IN (1, 2, 3, 4, 5, ...);

🎯 Conclusión – ¡Así es como resolvemos el problema N+1!

Cuando usas Django ORM, dejar sin atención el problema N+1 puede deteriorar seriamente el rendimiento. Sin embargo, si utilizas select_related y prefetch_related de manera adecuada, puedes minimizar el número de ejecuciones de SQL y mejorar significativamente la velocidad de carga de la página.

✅ Resumen

  • Usa select_related para relaciones ForeignKey (1:N)
  • Usa prefetch_related para relaciones ManyToMany o de referencia inversa
  • En cualquier caso, verifica el SQL ejecutado y optimiza según sea necesario
  • Si la velocidad de ejecución de las consultas se reduce, debes sospechar del problema N+1

📌 ¡No olvides leer también artículos relacionados!

¿Qué es el problema N+1 en Django ORM? ¿Por qué ocurre?

¡Ahora prueba resolver el problema N+1 utilizando select_related y prefetch_related! 🚀 Si hay algo que no entiendes o tienes más preguntas, no dudes en dejar un comentario o preguntar. 😊