Aurabase Logo
aurabasedocs
docsGuidesAudit performance

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
#
Baseline

Mesurer avant d’optimiser

§ 01

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.

cli
BASH
# Top 10 des queries les plus lentes (p99)
aura db slow-queries --limit 10 --since 7d
# Stats par endpoint API
aura db stats --by endpoint --sort p99 desc
#
Slow queries

pg_stat_statements en temps réel

§ 02

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.

top-10.sql
SQL
select query, calls, mean_exec_time, total_exec_time
from pg_stat_statements
where query not like '%pg_stat_statements%'
order by mean_exec_time desc
limit 10;
#
EXPLAIN ANALYZE

Lire le plan comme un pro

§ 03

Le plan vous dit pourquoi la query est lente. Les 4 signaux à chercher :

  • Seq Scan sur table > 10k lignes → index manquant
  • rows (estimated) ≠ rows (actual) de ±10× → stats obsolètes, analyze table_name
  • Nested Loop sur 100k+ lignes → hash join préférable, peut-être un WHERE manquant
  • Materialize ou Sort Method: external merge → RAM épuisée, work_mem à augmenter
debug
SQL
explain (analyze, buffers, format json)
select * from orders
where customer_id = 'abc' and created_at > now() - interval '30 days';
#
Indexes

Quand, quoi, comment

§ 04
  • 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 null pour 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.
#
Anti-patterns

Ce qui tue Postgres en prod

§ 05
  1. N+1 queries — faites un join ou utilisez !inner dans le SDK plutôt qu'un loop
  2. Pagination par OFFSET — au-delà de 1000, utilisez cursor-based (where id > last_seen)
  3. SELECT * sur vastes tables — demandez uniquement les colonnes nécessaires
  4. Transactions longues — elles bloquent VACUUM et causent bloat. Gardez < 1 seconde
  5. Policies RLS non-indexées — si votre policy utilise tenant_id = auth.tenant(), indexez tenant_id
Dernière mise à jour · 15 avr. 2026