Back

Comment repérer les requêtes de base de données qui nuisent aux performances de votre application

Comment repérer les requêtes de base de données qui nuisent aux performances de votre application

Votre tableau de bord se charge en 200 ms en local. En production, cela prend 8 secondes. Les utilisateurs se plaignent. Votre chef de produit demande ce qui ne va pas. Vous soupçonnez la base de données mais ne pouvez pas le prouver.

Cet article vous montre comment remonter des symptômes visibles par l’utilisateur jusqu’aux requêtes de base de données lentes, identifier les véritables goulots d’étranglement de performance de base de données, et distinguer les différentes causes profondes—avant de commencer à ajouter des index au hasard.

Points clés à retenir

  • Commencez le diagnostic par les symptômes visibles par l’utilisateur, pas par les mécanismes internes de la base de données—confirmez où le temps est réellement consommé avant d’investiguer les requêtes.
  • Utilisez EXPLAIN ANALYZE pour lire les plans de requête et identifier les parcours séquentiels, les boucles imbriquées et les écarts entre le nombre de lignes estimé et réel.
  • Suivez la latence p95 et p99 plutôt que les moyennes pour détecter les valeurs aberrantes qui pénalisent les vrais utilisateurs.
  • Distinguez les problèmes liés au CPU, aux E/S et à la contention de verrous—chacun nécessite des approches d’optimisation différentes.

Commencer par les symptômes visibles par l’utilisateur

Les pages lentes ne signifient pas toujours des requêtes lentes. Avant de plonger dans les mécanismes internes de la base de données, confirmez où le temps est réellement consommé.

Surveillez ces schémas :

  • Lenteur constante : Chaque requête vers /api/orders prend plus de 3 secondes. Probablement une seule requête coûteuse.
  • Requêtes en cascade : La page effectue 47 appels API séquentiels. Problème classique de requêtes N+1.
  • Latence incohérente : Le même point de terminaison varie de 50 ms à 5 secondes. Peut être une contention de verrous ou des échecs de cache.
  • Pics de timeout : Les requêtes échouent occasionnellement complètement. Vérifiez les verrous de table ou l’épuisement du pool de connexions.

Les DevTools du navigateur et vos logs d’API vous donnent le premier indice. Si le temps réseau est minimal mais le temps de réponse est élevé, le backend est le goulot d’étranglement. Si les logs backend montrent que la majorité du temps est passée dans les appels à la base de données, vous avez trouvé votre cible.

Techniques de détection essentielles pour l’analyse des performances des requêtes

Lire le plan de requête

Chaque base de données majeure explique comment elle exécute votre requête. C’est votre outil de diagnostic principal.

PostgreSQL :

EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

MySQL (8.0.18+) :

EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

SQLite :

EXPLAIN QUERY PLAN SELECT * FROM orders WHERE user_id = 123;

Recherchez les parcours séquentiels sur de grandes tables, les boucles imbriquées avec un nombre élevé de lignes, et les écarts entre les lignes estimées et réelles. Un plan montrant “Seq Scan” sur une table d’un million de lignes alors que vous attendiez une recherche par index révèle immédiatement le problème.

Note : Les planificateurs de requêtes changent entre les versions de base de données. Un plan qui fonctionnait dans PostgreSQL 14 peut différer dans PostgreSQL 16. Ne supposez pas que les mises à jour corrigent automatiquement les mauvaises requêtes.

Activer les logs de requêtes lentes

Configurez votre base de données pour enregistrer les requêtes dépassant un seuil.

PostgreSQL utilise pg_stat_statements pour les statistiques d’exécution agrégées. Pour la journalisation par requête, utilisez log_min_duration_statement. Le Performance Schema et le schéma sys de MySQL exposent les requêtes lentes sans le cache de requêtes obsolète. SQLite nécessite un chronométrage au niveau de l’application car il n’a pas de journalisation de requêtes lentes intégrée.

Définissez les seuils de manière conservatrice en production. Commencez à 100 ms, puis resserrez au fur et à mesure que vous corrigez les problèmes évidents.

Mesurer les percentiles, pas les moyennes

Le temps de requête moyen masque les valeurs aberrantes. Une requête avec une moyenne de 50 ms peut atteindre 2 secondes au p99—affectant systématiquement 1 % de vos utilisateurs.

Suivez la latence p95 et p99. Si votre p99 est 10 fois supérieur à votre médiane, vous avez un problème de latence de queue qui mérite investigation.

Distinguer CPU vs E/S vs contention de verrous

Un temps de requête élevé signifie différentes choses :

  • Lié au CPU : Calculs complexes, tris volumineux ou opérations regex. Le plan de requête montre un “coût” élevé sur les nœuds gourmands en calcul.
  • Lié aux E/S : Lecture de beaucoup de données depuis le disque. Surveillez les parcours séquentiels et les index manquants.
  • Contention de verrous : Requêtes en attente d’autres transactions. Vérifiez pg_stat_activity (PostgreSQL) ou SHOW PROCESSLIST (MySQL) pour les requêtes bloquées.

Chacun nécessite des approches différentes d’optimisation des requêtes SQL. Ajouter un index n’aidera pas une agrégation liée au CPU.

Détection axée sur l’observabilité avec le traçage distribué

OpenTelemetry vous permet de corréler les requêtes lentes avec des spans de base de données spécifiques. Une trace montrant votre point de terminaison /api/dashboard révèle exactement quelles requêtes ont consommé du temps.

Configurez votre ORM ou pilote de base de données pour émettre des spans avec le chronométrage des requêtes. Vous verrez clairement le problème N+1 : 50 spans SELECT identiques là où un seul devrait exister.

Avertissement de sécurité : N’enregistrez pas le SQL complet avec les paramètres dans les traces de production. Les identifiants utilisateur, les e-mails et autres données personnelles finissent dans votre plateforme d’observabilité. Enregistrez plutôt les empreintes de requêtes (modèles paramétrés).

Pièges courants à éviter

  • Ajouter des index aveuglément : Les index accélèrent les lectures mais ralentissent les écritures. Vérifiez que le plan de requête utilise réellement votre nouvel index.
  • Se fier aux moyennes : Cette moyenne de 50 ms cache les valeurs aberrantes de 5 secondes qui pénalisent les vrais utilisateurs.
  • Optimisation universelle : “Augmenter work_mem” n’est pas un conseil universel. Mesurez d’abord.
  • Journaliser le SQL brut : Risque de sécurité et de conformité. Utilisez des empreintes paramétrées.

Conclusion

Repérer les goulots d’étranglement de performance de base de données commence par les symptômes, pas par des suppositions. Remontez des pages lentes aux points de terminaison lents, des points de terminaison lents aux requêtes lentes, et des requêtes lentes à leurs plans d’exécution. Mesurez les percentiles, distinguez les problèmes CPU/E/S/verrous, et utilisez le traçage distribué pour relier les symptômes frontend aux causes backend.

C’est seulement alors que vous devriez optimiser.

FAQ

Vérifiez vos logs d'API pour les répartitions du temps de réponse. Si la latence réseau est faible mais que le temps de réponse backend est élevé, le serveur est le goulot d'étranglement. Au sein de votre backend, mesurez le temps passé dans les appels à la base de données par rapport à la logique applicative. La plupart des frameworks et outils APM peuvent afficher cette répartition, vous aidant à confirmer si les requêtes sont réellement en cause.

EXPLAIN affiche le plan de requête que la base de données prévoit d'utiliser sans exécuter la requête. EXPLAIN ANALYZE exécute réellement la requête et rapporte les temps réels et le nombre de lignes. Utilisez EXPLAIN pour des vérifications rapides et EXPLAIN ANALYZE lorsque vous avez besoin de données de performance précises. Soyez prudent avec EXPLAIN ANALYZE sur les opérations d'écriture car il exécutera les modifications.

Les index consomment du stockage et ralentissent les opérations INSERT, UPDATE et DELETE car la base de données doit les maintenir. De plus, le planificateur de requêtes peut ne pas utiliser votre index s'il estime qu'un parcours séquentiel serait plus rapide. Vérifiez toujours avec EXPLAIN ANALYZE que votre nouvel index améliore réellement les requêtes spécifiques que vous ciblez.

Activez la journalisation des requêtes ou utilisez le traçage distribué pour voir toutes les requêtes exécutées par demande. Recherchez des schémas où le même modèle de requête s'exécute plusieurs fois avec des paramètres différents. Les ORM causent souvent cela lors du chargement d'enregistrements liés un par un. La solution est généralement le chargement anticipé (eager loading) ou le regroupement des requêtes en une seule demande avec une clause IN.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay