Une base de données qui ralentit arrive toujours au pire moment : le produit grandit, les utilisateurs sont là, et soudain les requêtes qui prenaient 20 millisecondes en prennent 800. La tentation immédiate est de conclure que la base est « trop petite » et de prévoir une plus grosse machine, ou de réécrire le schéma. C’est presque toujours une erreur de diagnostic : on traite le symptôme avant d’avoir trouvé la cause.
Dans la plupart des cas observés sur des applications de PME, le problème n’est pas la capacité de la machine mais la façon dont la base est utilisée : requêtes sans index, chargement de trop de lignes, accès répétés au même disque, verrous qui s’accumulent. Avant de dépenser dans du matériel, il existe une séquence de vérifications qui règle une grande partie des cas, et c’est elle qu’on détaille ici.
Cet article donne un plan d’action ordonné pour scaler une base de données relationnelle classique (PostgreSQL, MySQL, MariaDB), avec les signaux qui indiquent quand passer à l’étape suivante. Il s’agit de réutiliser directement ce plan sur votre propre base, sans matériel neuf ni réécriture. Il prolonge le plan pour scaler une API : quand on mesure une API lente, c’est très souvent la base qui cède en premier.
Mesurer avant de toucher
Aucune décision ne se prend sans chiffres. Sur une base qui ralentit, la première action est de regarder les requêtes lentes : PostgreSQL expose pg_stat_statements, MySQL son slow query log. Ces deux outils donnent la liste des requêtes qui consomment du temps, triées par durée cumulée. C’est la seule façon de savoir si le problème vient d’une requête précise ou d’une dégradation générale.
En parallèle, mesurez le taux de cache : si cache hit ratio tombe sous 95 %, c’est que les données chaudes ne tiennent pas en mémoire. Et surveillez les connexions actives : une base saturée montre souvent des centaines de connexions en attente d’un verrou. Un pooler de connexions comme PgBouncer, ou celui intégré à Supabase, évite qu’une application serverless déployée sur Vercel ouvre une connexion par requête. Ces trois mesures, requêtes lentes, cache et verrous, suffisent à classer le problème dans la bonne catégorie.
Ne commencez aucune optimisation avant d’avoir ces chiffres. Une optimisation sans mesure est une modification de la base sans savoir si elle servira, et elle peut dégrader le comportement des autres requêtes.
Les index : le premier levier, presque toujours sous-utilisé
La cause la plus fréquente d’une base lente est un scan complet de table sur des données volumineuses. La requête est correcte, les données sont là, mais le moteur lit chaque ligne pour en garder quelques-unes. Un index adapté transforme cette lecture de millions de lignes en une recherche de quelques dizaines.
Le réflexe utile est de prendre chaque requête lente et de regarder le plan d’exécution : l’outil EXPLAIN montre si la ligne comporte un Seq Scan et quels filtres sont appliqués. L’index se construit sur les colonnes utilisées dans le WHERE, puis dans le JOIN, puis dans le ORDER BY, dans cet ordre. Pour un filtre qui combine plusieurs colonnes, un index composite est souvent plus efficace que plusieurs index séparés.
Un piège fréquent : les index appliqués sur des colonnes transformées par une fonction. WHERE date_creation > ... utilise un index, WHERE EXTRACT(YEAR FROM date_creation) = 2026 ne l’utilise pas, car la colonne est modifiée avant la comparaison. La correction est de réécrire la condition pour qu’elle porte sur la colonne brute, sans fonction.
Réduire ce que chaque requête transporte
Une fois les index en place, le deuxième goulot est la quantité de données transportées. Une application qui charge 500 colonnes pour en afficher 5, ou qui récupère 10 000 lignes pour en montrer 50, fait travailler la base pour rien. Les opérateurs LIMIT avec pagination et la sélection explicite des colonnes réduisent cette charge sans toucher au schéma.
Le même raisonnement s’applique aux jointures : charger les lignes d’une table associée en bloc avec une ou deux requêtes préparées est souvent plus rapide que de laisser l’application déclencher une requête par ligne. Le fameux problème des N+1 requêtes, où chaque élément d’une liste déclenche sa propre interrogation, est une cause classique de ralentissement qui n’a rien à voir avec la taille de la base. On le retrouve en tête des causes fréquentes d’une API lente. Les ORM comme Prisma ou Drizzle, courants dans le code généré par IA, le produisent facilement quand les relations sont chargées dans une boucle ; activer les logs SQL en développement suffit à le repérer.
Sur les gros volumes, vérifiez aussi ce que le réseau transporte. Une application qui appelle la base depuis un autre serveur peut être limitée par la latence du lien plus que par la base elle-même. Regrouper les accès et réduire le volume renvoyé fait souvent baisser les temps de réponse plus vite qu’une optimisation du moteur.
Quand la mémoire et le disque deviennent le facteur
Si les requêtes sont indexées et légères mais que le cache reste sous les 95 %, le problème devient matériel. Les données fréquemment accédées doivent tenir en mémoire : sur un serveur dédié, attribuer 50 à 70 % de la RAM à shared_buffers (PostgreSQL) ou innodb_buffer_pool_size (MySQL) est le réglage de base. Beaucoup d’installations par défaut sont volontairement prudentes et laissent la mémoire inutilisée.
Vérifiez ensuite le type de stockage. Un disque dur mécanique qui sert de base à une application avec de l’écriture régulière est un goulot permanent : les écritures aléatoires sont lentes, et les temps de réponse sont instables. Passer sur un SSD règle ce problème sans changer une ligne de code, et c’est souvent l’achat le plus rentable. La latence d’écriture, pas la taille, est le facteur qui plombe les temps de réponse en production.
Un signal fiable pour décider : si la charge CPU de la base reste faible alors que les requêtes sont lentes, le problème est très probablement l’entrée-sortie. À l’inverse, une CPU saturée avec des requêtes pourtant indexées indique un volume de travail réel qui ne se règle pas par la configuration.
Lire les réplicas et le partitionnement
Quand la base principale est correctement configurée mais que la charge reste trop élevée, les deux leviers suivants sont structurels. Un réplica en lecture, un serveur qui reçoit une copie des données et ne sert que les requêtes en lecture, décharge la base principale de la majorité du trafic d’une application classique. La mise en place demande de rediriger les requêtes de lecture vers le réplica, et l’écart de quelques secondes entre les deux copies doit être accepté par les fonctionnalités concernées.
Le partitionnement, lui, découpe une table volumineuse en plusieurs segments selon une clé, par exemple la date : chaque segment reste de taille raisonnable, les index restent efficaces et les purges deviennent triviales, car supprimer un segment ancien est immédiat au lieu de supprimer ligne par ligne. Il s’agit d’une évolution de schéma, mais sans réécriture applicative, le moteur masque la découpe.
Les offres managées (Supabase, Amazon RDS, Google Cloud SQL) proposent ces réplicas en quelques clics. Ces deux solutions s’appliquent quand la base est saine mais que le volume croît : c’est le bon moment, avant que le matériel ne dicte la décision. Commencer par les index et la configuration retarde toujours ce besoin, et le rend plus simple quand il arrive. C’est l’une des fondations à poser pour préparer un produit à la croissance.
Passer à l’action : scaler vos données
Le plan tient en quatre mots : mesurer, indexer, alléger, puis seulement ajuster le matériel. Il s’applique particulièrement bien aux produits construits vite, avec Lovable, Bolt ou Cursor : le schéma a été généré pour faire marcher la démo, les index manquent, l’ORM déclenche des N+1 en cascade, et tout se dégrade au moment où les utilisateurs arrivent.
Ce diagnostic fait partie de ce qu’on regarde en premier quand on reprend un produit pour le faire passer à l’échelle : relevé des requêtes lentes, plan d’index, réglages mémoire, puis réplicas ou partitionnement si le volume l’exige. Chaque étape est validée par une mesure avant et après, et vous gardez votre application et votre schéma.

