Audit performance p99
Identifier les slow queries, comprendre EXPLAIN ANALYZE, stratégies d’indexation, et les 5 anti-patterns qui tuent Postgres en production.
14 min de lecture·Niveau avancé·Révisé le 15 avr. 2026
Un audit commence par des chiffres. Le Studio expose p50/p95/p99 par endpoint et par query. Captez une baseline sur 7 jours avant tout changement.
L'extension pg_stat_statements est activée par défaut. Elle agrège chaque query normalisée avec mean_exec_time, calls, rows. Le Studio affiche ça dans un tableau triable.
Le plan vous dit pourquoi la query est lente. Les 4 signaux à chercher :
Seq Scansur table > 10k lignes → index manquantrows (estimated) ≠ rows (actual)de ±10× → stats obsolètes,analyze table_nameNested Loopsur 100k+ lignes → hash join préférable, peut-être un WHERE manquantMaterializeouSort Method: external merge→ RAM épuisée,work_memà augmenter
- B-tree (défaut) : égalité, range, order by. 80% des cas.
- GIN : full-text search, JSONB, tableaux.
using gin (to_tsvector('french', body)). - GiST : géospatial (PostGIS), recherche par similarité (pg_trgm).
- HNSW (pgvector) : recherche vectorielle, > 100k vecteurs.
- Partial : conditions courantes,
where deleted_at is nullpour soft delete. - Covering :
include (...)pour éviter le lookup sur la table.
Attention
Chaque index ralentit les INSERT/UPDATE/DELETE (~5-15% par index). Droppez les indexes non utilisés —
pg_stat_user_indexes les liste avec idx_scan = 0.- N+1 queries — faites un join ou utilisez
!innerdans le SDK plutôt qu'un loop - Pagination par OFFSET — au-delà de 1000, utilisez cursor-based (
where id > last_seen) - SELECT * sur vastes tables — demandez uniquement les colonnes nécessaires
- Transactions longues — elles bloquent VACUUM et causent bloat. Gardez < 1 seconde
- Policies RLS non-indexées — si votre policy utilise
tenant_id = auth.tenant(), indexeztenant_id
Dernière mise à jour · 15 avr. 2026