Pourquoi votre listing PostgreSQL rame (et comment 1 index le rend instantané)

15 vues
Base de donnéesPerformance
Pourquoi votre listing PostgreSQL rame (et comment 1 index le rend instantané)
Un listing lent n’est pas une fatalité. Découvrez comment un simple index PostgreSQL accélère vos tableaux de bord de 100x — sans changer une ligne de code.

“Le tableau dans notre dashboard met plusieurs secondes à charger…”
C’est une remarque que j’entends souvent en maintenance d’applications existantes.

On pense parfois à :

  • Un composant frontend trop lourd,
  • Un ORM qui génère des requêtes inefficaces,
  • Un serveur un peu juste…

Mais dans la majorité des cas que j’ai analysés, la cause est bien plus simple :
👉 la table n’est pas indexée sur les colonnes utilisées pour le tri ou les filtres.

🔍 Test réel sur 100 000+ lignes

J’ai simulé un cas métier classique avec une table invoices contenant 100 000 factures réalistes (statuts, dates, montants aléatoires).
Objectif : reproduire un listing de dashboard typique.

❌ Requête de listing SANS index

n1ql
SELECT * FROM invoices
WHERE status = 'paid'
ORDER BY created_at DESC
LIMIT 50;

Résultat de EXPLAIN ANALYZE :

crmsh
Execution Time: 26.976 ms
→ PostgreSQL parcourt 70 000 lignes, filtre, puis trie partiellement.

Même avec 100k lignes, 27 ms par requête, multiplié par des dizaines d’utilisateurs, ça devient frustrant.

✅ Solution : un index composite bien ciblé

n1ql
CREATE INDEX idx_invoices_status_created ON invoices (status, created_at DESC);

Même requête, après l’index :

crmsh
Execution Time: 0.200 ms
→ PostgreSQL va directement aux 50 bonnes lignes, triées, sans scan.

🚀 Résultat : 26.976 ms → 0.200 ms = 135× plus rapide.
Et aucune modification dans l’application.

⚖️ Et l’impact sur les écritures ? J’ai mesuré.

J’ai inséré 10 000 nouvelles lignes avant et après la création de l’index :

Sans index => 52.4 ms
Avec index => 56.4 ms

➡️ Surcoût : +4 ms pour 10 000 lignes
→ Soit +0.0004 ms par ligne.

💡 Dans un dashboard, on a souvent des centaines de lectures pour une écriture.
Gagner 26.8 ms par requête utilisateur pour un coût quasi nul en écriture ?
Le compromis est évident.

❌ Erreur courante à éviter

Ne créez pas :

  • Un index sur status seul → pas d’aide pour le tri.
  • Un index sur created_at seul → pas d’aide pour le filtre.

✅ **Seul l’index composite **(status, created_at DESC) **couvre les deux besoins :
**

  • Filtrer rapidement (WHERE status = 'paid'),
  • Récupérer les résultats déjà triés (ORDER BY created_at DESC).

📊 Le vrai coût ? Ce n’est pas l’index… c’est son absence

  • Sans index : le listing rame, les utilisateurs attendent.
  • Avec un bon index : réactivité immédiate.
  • Le surcoût en écriture ? Négligeable dans la quasi-totalité des applications métier.

La vraie erreur n’est pas d’avoir des index.
C’est d’en avoir trop (inutiles)… ou aucun (quand il en faut).

🔍 Avant de chercher une solution complexe…

… posez-vous une question simple :

« Est-ce que mon listing est correctement indexé ? »

Utilisez EXPLAIN ANALYZE.
Si vous voyez un Seq Scan sur une table volumineuse, la solution est souvent un index.

Et dans 90 % des cas, une seule ligne SQL suffit à transformer une expérience lente en une interface fluide.

✨ Bonus : nettoyez les index inutiles

Un index jamais utilisé ne sert qu’à ralentir les écritures.
Trouvez-les avec :

pgsql
SELECT indexname, idx_tup_read
FROM pg_stat_user_indexes
WHERE idx_tup_read = 0;

✅ Conclusion :

Un listing lent n’est pas une fatalité technique.
Souvent, la solution tient en une ligne :

n1ql
CREATE INDEX