Chasser les N+1 et éliminer les requêtes inutiles dans Laravel
Le travail sur la performance est souvent ennuyeux.
Il ne s'agit pas toujours d'histoires héroïques où l'on réduit la latence de 80 %. La plupart du temps, il s'agit de nettoyage. Vous trouvez des requêtes que vous ne saviez pas exécuter. Ensuite, vous les supprimez.
Si votre application Laravel grandit, vous rencontrez probablement ces trois problèmes.
1. Les requêtes N+1 cachées
On ne peut pas corriger ce que l'on ne voit pas. Utilisez un outil comme beyondcode/laravel-query-detector dans votre environnement local. Il vous indique quand vous utilisez le modèle de boucle avec chargement paresseux (loop-and-lazy-load).
Ne l'exécutez pas en production. Cela ajoute une surcharge (overhead). Ne l'enregistrez que lorsque votre application est en mode local ou de test.
2. Le gaspillage lié à l'Eager Loading
On corrige souvent les problèmes de N+1 en ajoutant with(). Mais cela crée un nouveau problème. Vous pourriez charger préventivement (eager-load) une relation que votre vue n'utilise plus.
Si une refonte supprime une colonne d'une table, vous devez supprimer l'appel with() correspondant dans votre contrôleur. Vous payez pour des données que vous jetez.
Considérez chaque chargement anticipé comme une revendication. Si vous n'utilisez pas les données, supprimez la revendication.
3. Le recalcul des mêmes données
Certaines valeurs restent identiques pendant toute la durée de la requête. Si vous les calculez plusieurs fois, vous gaspillez du CPU. Utilisez la mémoïsation pour corriger cela.
Exemple :
protected ?string $defaultConnection = null;
public function getDefaultConnectionName(): string
{
return $this->defaultConnection ??= $this->resolveDefaultConnection();
}
L'opérateur ??= calcule la valeur une seule fois et la réutilise pour le reste de la requête.
4. Les pièges des requêtes de tableau de bord
Les tableaux de bord exécutent souvent une requête count() distincte pour chaque carte. Si vous avez six cartes, vous exécutez six requêtes.
Faites plutôt ces deux choses :
- Groupez vos comptages. Récupérez tous les totaux d'une table en une seule requête.
- Utilisez un cache court. Les statistiques d'un tableau de bord n'ont pas besoin d'être actualisées à la seconde près. Mettez-les en cache pendant cinq minutes.
Un visiteur paie le coût de la requête. Tous les autres bénéficient du résultat mis en cache.
Conseil final : Prévenir les régressions
Les nettoyages échouent si les développeurs réintroduisent le mauvais code plus tard. Utilisez Pest pour vérifier (assert) vos nombres de requêtes. Définissez un plafond pour le nombre de requêtes qu'une page peut exécuter. Si un développeur ajoute un N+1, le test échouera.
L'optimisation consiste principalement à supprimer. Supprimez les chargements inutilisés. Supprimez les valeurs recalculées. Supprimez les requêtes inutiles.
