€0.00 — free as in speechtonight's forecast: clear skies over production Cache: warm · Deploys: fair, 0% rollbacks expectedset by moonlight, shipped before dawn · deploy freely Page A2

The Daily Commit The Nightly Build

Dev news, typeset daily — PHP · AI · The Wider Stack

The developer's evening paper — PHP · AI · The Wider Stack

mardi 22 septembre 2026 Vol. I — No. 596 · Édition du matinÉdition du soir EN DE FR ES

Dev · Actus

Un index PostgreSQL mal calibré a transformé une requête de 40 ms en quatre secondes

Un développeur relate un bug PostgreSQL récurrent : un index sur customer_id existait mais était ignoré car la requête triait aussi par created_at.

sélectionné par Sönke

Un index composite a réduit le temps d'exécution de quatre secondes à neuf millisecondes, menant à une routine en quatre étapes basée sur EXPLAIN ANALYZE.

Sur la table order_events, qui compte environ quatre millions de lignes d'événements liés à des commandes en ligne, une requête censée récupérer les 30 derniers jours d'activité pour un customer_id donné s'est mise à bloquer lors d'une intervention tardive. Un index sur customer_id avait été ajouté trois semaines plus tôt, mais EXPLAIN ANALYZE a montré que PostgreSQL exécutait quand même un balayage séquentiel de toute la table, faisant passer le temps d'exécution attendu de 40 millisecondes à environ quatre secondes.

order_events query
SELECT * FROM order_events
WHERE customer_id = 8842
AND created_at > now() - interval '30 days'
ORDER BY created_at DESC;

La cause venait d'un décalage entre l'index et la clause ORDER BY de la requête. L'index ne portait que sur customer_id, ce qui permettait à PostgreSQL de retrouver rapidement les lignes du client, mais l'obligeait ensuite à toutes les charger en mémoire et à les trier selon created_at. Un index composite sur (customer_id, created_at DESC), correspondant exactement au schéma d'accès de la requête, a fait chuter le temps d'exécution à neuf millisecondes.

La même erreur s'était déjà produite sur une application de planification pour le secteur de la santé et sur un outil d'analyse pour un client logistique, toujours parce qu'un index ne couvrait que la clause WHERE sans tenir compte des colonnes de tri, de regroupement ou de jointure. Cela a conduit à une routine en quatre étapes appliquée à chaque requête lente : exécuter EXPLAIN ANALYZE et repérer un Seq Scan sur des tables de plus de quelques milliers de lignes ; examiner les colonnes utilisées dans ORDER BY, GROUP BY et JOIN pour déterminer si un index composite vaut mieux que plusieurs index simples ; vérifier la sélectivité des colonnes, car un champ à faible cardinalité comme un order_status limité à trois valeurs n'apporte guère d'aide seul et doit être combiné à une colonne plus sélective ; et enfin consigner les temps réels en millisecondes mesurés par EXPLAIN ANALYZE avant et après chaque correction plutôt que de se fier à une impression.

Lire la source originale (en anglais) ↗

Évaluer cet article : 0

Tribune des lecteurs

Pas encore de contributions — lance le débat.

The Daily CommitThe Nightly Build — Page A1