Las cargas perezosas y el “problema N+1” con TypeORM.

Ángel De La Cruz Sánchez
3 min readOct 4, 2023

--

Cover image for nest.js + TypeORM + PostgreSQL

Las cargas perezosas, o “lazy loading”, son una técnica en TypeORM (y en otros ORM) que permite cargar relaciones entre entidades solo cuando se accede a ellas. Esto puede ser útil para mejorar el rendimiento, especialmente cuando trabajas con relaciones complejas y no siempre necesitas todos los datos relacionados.

Aquí hay una descripción de cómo puedes utilizar la carga perezosa en TypeORM:

1. Definir la Relación como Perezosa

Puedes configurar una relación como perezosa utilizando una Promise en el tipo de la relación. Por ejemplo:

@Entity()
class User {
// ...

@OneToMany(() => Post, post => post.user)
posts: Promise<Post[]>; // Nota el uso de Promise aquí
}

2. Cargar la Relación Perezosamente

Cuando recuperas una entidad que tiene una relación perezosa, la relación no se carga automáticamente. En su lugar, puedes cargarla cuando la necesites utilizando la Promise:

const user = await getRepository(User).findOne(userId);

// La relación 'posts' no se ha cargado aún
const posts = await user.posts; // La relación se carga aquí

3. Consideraciones de Rendimiento

La carga perezosa puede mejorar el rendimiento al evitar la carga de datos innecesarios. Sin embargo, también puede llevar a la “problema N+1” si no tienes cuidado. Por ejemplo, si cargas muchos usuarios en un bucle y luego accedes a sus posts perezosamente dentro del bucle, terminarás haciendo muchas consultas adicionales a la base de datos. Puedes evitar esto utilizando la opción relations en el método find o findOne, como se mencionó anteriormente, para cargar todas las relaciones necesarias en una sola consulta.

4. Transacciones

Ten en cuenta que la carga perezosa depende de que la conexión a la base de datos aún esté disponible cuando accedas a la relación. Si estás utilizando transacciones y la transacción se ha cerrado antes de que accedas a la relación, puedes encontrar problemas. Asegúrate de entender el ciclo de vida de tus transacciones y conexiones si estás utilizando la carga perezosa.

La carga perezosa es una herramienta útil en TypeORM que te permite tener un control más preciso sobre cuándo se cargan los datos relacionados. Como con muchas características poderosas, viene con algunas complejidades y trampas potenciales, así que es importante entender bien cómo funciona y probar cuidadosamente tu código.

El problema N+1:

Es un problema común en la carga perezosa, donde terminas haciendo muchas consultas adicionales a la base de datos. Aquí te muestro cómo puedes evitarlo utilizando la opción relations en TypeORM.

Supongamos que tienes las siguientes entidades User y Post, y quieres cargar todos los usuarios junto con sus posts relacionados:

@Entity()
class User {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@OneToMany(() => Post, post => post.user)
posts: Promise<Post[]>; // Relación perezosa
}

@Entity()
class Post {
@PrimaryGeneratedColumn()
id: number;

@Column()
title: string;

@ManyToOne(() => User, user => user.posts)
user: User;
}

Carga Perezosa con Problema N+1

Si intentas cargar los usuarios y sus posts en un bucle utilizando la carga perezosa, terminarás con el problema N+1:

const users = await getRepository(User).find();

for (const user of users) {
const posts = await user.posts; // Consulta adicional para cada usuario
// ...
}

Esto resultará en una consulta para cargar los usuarios, y luego una consulta adicional para cada usuario para cargar sus posts, lo que lleva a N+1 consultas en total.

Evitar el Problema N+1

Puedes evitar el problema N+1 utilizando la opción relations para cargar todas las relaciones necesarias en una sola consulta:

const users = await getRepository(User).find({
relations: ['posts'] // Carga los posts junto con los usuarios
});

for (const user of users) {
const posts = await user.posts; // Los posts ya están cargados, sin consulta adicional
// ...
}

Esto resultará en una sola consulta que carga todos los usuarios y sus posts relacionados, evitando el problema N+1 y mejorando potencialmente el rendimiento.

La opción relations es una herramienta poderosa en TypeORM que te permite tener un control preciso sobre cómo se cargan las relaciones, y puede ser especialmente útil cuando trabajas con relaciones perezosas y quieres evitar el problema N+1.

Gracias a Chat GPT.

--

--

Ángel De La Cruz Sánchez

Mi objetivo ha sido siempre crear soluciones tecnológicas innovadoras que impulsen el crecimiento.