Le problème N+1
Le problème N+1 se produit lorsqu'une requête initiale est exécutée pour obtenir une relation parente, puis des requêtes supplémentaires sont effectuées pour récupérer chaque enfant individuellement. Ce scénario est couramment rencontré lors de l’utilisation des ORM.
Pour illustrer ce problème, prenons un exemple concret. Supposons que nous ayons une base de données qui répertorie des auteurs et les livres qu’ils ont écrits. Si nous voulons récupérer la liste des auteurs avec leurs livres associés, cela pourrait être implémenté comme suit :
$authors = $pdo->query('SELECT * FROM author')->fetchAll();
foreach ($authors as $author) {
$author['books'] = $pdo->query('SELECT * FROM book WHERE author_id = ' . $author['id'])->fetchAll();
}
Dans ce code, nous pouvons observer que les performances de l’application se dégraderont rapidement à mesure que le nombre d’auteurs et de livres augmentera. Par exemple, si nous récupérons 10 auteurs, cela entraînera l’exécution de 11 requêtes pour obtenir toutes les informations nécessaires :
- 1 requête pour récupérer les 10 auteurs
- 10 requêtes supplémentaires pour récupérer les livres de chaque auteur
Ce problème est courant avec les associations OneToMany
et ManyToOne
de Doctrine, car par défaut, Doctrine génère des classes Proxy pour récupérer les relations enfants uniquement lorsqu'elles sont demandées. Dans ce cas, une requête est exécutée à chaque appel de la méthode getBooks
pour récupérer les informations correspondantes.
Pour éviter cette inefficacité, nous pouvons utiliser des jointures SQL pour récupérer les informations des auteurs et des livres qu’ils ont écrits en une seule requête. Voici comment nous pourrions modifier l’exemple précédent :
$authors = $pdo->query('SELECT * FROM author JOIN book ON author.id = book.author_id')->fetchAll();
Dans le cadre de Laravel, cette solution peut être implémentée de manière plus élégante en utilisant la méthode with
:
$authors = Author::with('books')->get();
Cela permet de récupérer tous les auteurs et leurs livres associés en une seule requête, améliorant ainsi considérablement les performances de l’application.
Aucune page ou chapitre n'a été ajouté à cet article.