Le déploiement annonce une migration terminée, mais la liste des commandes reste lente. Quelques minutes plus tôt, la création de l’index avait échoué ; une relance n’a ensuite affiché qu’un avis indiquant que son nom existait déjà. Le risque est de prendre cette absence de nouvelle erreur pour la réparation de l’objet. Entre le journal du déploiement et la recherche utilisée par le gestionnaire, la preuve manque encore.
En pratique, la réception doit couvrir quatre questions : avons-nous le bon objet, la bonne définition, un état valide et un résultat acceptable pour l’application ? Le nom ne répond qu’à une partie de la première. Ce dossier traite précisément la reprise après CREATE INDEX CONCURRENTLY, avec les références PostgreSQL 18 consultées le 24 octobre 2026. Le comportement décrit n’est pas une nouveauté annoncée ce mois-ci.
Pour une application de gestion ou un SaaS, notre approche du développement web sur mesure consiste à relier les changements de structure aux parcours réellement servis. Une migration déclarée exécutée et un écran fonctionnel ne constituent pas deux preuves équivalentes : l’équipe doit pouvoir expliquer ce qui a changé dans la base et ce qui a été accepté côté métier.
Un audit technique de l’application aide à retrouver cette chaîne lorsque le code PHP, Doctrine, la CI et l’exploitation portent chacun une partie de l’information. Nous allons construire une décision de reprise, examiner les limites des indicateurs et préparer une recette. Les exemples sont fictifs ; aucune performance client ni intervention sur une base réelle n’est revendiquée.
Dans quel cas vérifier un index après le déploiement
Une recherche dont la lenteur persiste après la correction
Le bon point de départ est une requête identifiable : les commandes ouvertes d’un client, classées par date, par exemple. Conservez le SQL réellement envoyé par le backend, ses paramètres et le rôle de connexion. Le nom de l’écran ne suffit pas, car deux filtres frontend peuvent produire des requêtes différentes. Un cache peut également masquer la lenteur sur un compte et la laisser apparaître sur un autre.
Rapprochez ensuite la version applicative, l’heure de migration et le journal complet de création. Un message antérieur d’annulation ou d’échec mérite d’être conservé, même si le dernier job est vert. Le signal faible est souvent cet écart : une correction structurelle annoncée sans changement observable du parcours. Il justifie une inspection ciblée, pas une reconstruction générale de tous les index.
Un périmètre qui n’englobe pas tous les incidents PostgreSQL
Ce diagnostic vise un index ajouté ou reconstruit dans un processus de livraison. Une saturation CPU, une connexion indisponible ou une erreur fonctionnelle peut avoir une autre cause. Ne concluez pas à un index invalide simplement parce qu’un écran est lent. Commencez par établir la chronologie et par retrouver l’objet visé dans la bonne base et le bon schéma.
Le changement de collation après une mise à jour système suit une autre logique : il faut alors qualifier les règles de comparaison et les objets dépendants. Ces deux problèmes peuvent conduire à examiner des index, mais leurs preuves initiales et leurs corrections ne sont pas interchangeables. Les traiter séparément évite de transformer une procédure précise en remède universel.
Pourquoi le nom de l’index ne prouve pas sa construction
La relance qui évite une erreur sans réparer l’état
La référence CREATE INDEX précise qu’IF NOT EXISTS évite l’erreur lorsqu’une relation de même nom existe, sans garantir que sa définition corresponde à celle demandée. Après certains échecs de construction concurrente, un index invalide reste présent. La combinaison explique le faux succès : la relance peut constater le nom et ne rien reconstruire.
Dans votre procédure, distinguez donc « commande relancée » et « postcondition établie ». Le premier fait décrit une action ; le second doit être démontré. Enregistrer la migration comme terminée après un simple contrôle de présence produit une dette opérationnelle : le prochain intervenant verra un historique rassurant, alors que l’état physique exige encore une décision documentée.
Un objet invalide peut encore avoir un effet
La même documentation décrit un coût de maintenance possible pour l’index invalide, ignoré pour les recherches. Elle signale aussi un cas plus surprenant : après un échec pendant la seconde analyse d’une construction unique, l’index invalide peut continuer à faire respecter l’unicité. Il ne faut donc déduire ni son innocuité ni son comportement d’écriture de son seul état « invalide ».
Paradoxalement, une erreur d’unicité sur une nouvelle saisie ne prouve pas que toutes les données historiques respectent la règle attendue, ni que l’objet est prêt pour les lectures. Pour une référence client ou une clé de rapprochement ERP, séparez les contrôles de données, l’état de construction et le comportement observé. La correction d’éventuels doublons reste une décision métier traçable.
Lire ensemble identité, définition et indicateurs du catalogue
Trois indicateurs, trois questions différentes
Le catalogue pg_index distingue indisvalid, qui indique la validité pour les requêtes, indisready, qui concerne la prise en compte des insertions, et indislive, faux lorsque l’objet est en cours de suppression. Ces champs ne sont pas trois synonymes d’un état « prêt ». Une observation doit conserver leurs valeurs séparées.
Les réunir dans un contrôle applicatif est une politique d’acceptation, pas une réécriture des règles du moteur. Même des indicateurs favorables ne garantissent pas que le planificateur choisira cet index pour une requête donnée. Le catalogue documente aussi une condition liée aux transactions avec indcheckxmin. La décision de performance demandera donc une observation supplémentaire, avec les connexions effectivement utilisées.
Retrouver l’objet sans dépendre du chemin de recherche
Cette requête de lecture vise explicitement le schéma et le nom de l’index. Elle affiche également sa table et une reconstruction de sa définition grâce à pg_get_indexdef. Adaptez les deux valeurs avec l’équipe base et conservez le contexte de connexion. L’absence de ligne signifie d’abord que cet objet n’a pas été retrouvé dans cette base.
SELECT current_database() AS base,
ns.nspname AS schema_index,
idx.relname AS nom_index,
tbl.oid::regclass AS table_indexee,
i.indisvalid, i.indisready, i.indislive,
i.indisunique, i.indcheckxmin,
pg_get_indexdef(idx.oid) AS definition
FROM pg_index AS i
JOIN pg_class AS idx ON idx.oid = i.indexrelid
JOIN pg_namespace AS ns ON ns.oid = idx.relnamespace
JOIN pg_class AS tbl ON tbl.oid = i.indrelid
WHERE ns.nspname = 'app'
AND idx.relname = 'commande_ouverte_idx';
La définition reconstruite n’est pas le texte original de la migration. Pour la comparer, examinez la table, la méthode, les clés et leur ordre, les expressions, le prédicat, les colonnes incluses et l’unicité. Une comparaison textuelle brute peut produire de fausses différences de présentation ; une comparaison limitée au nom peut ignorer une différence décisive. Le contrat attendu doit préciser les propriétés réellement voulues.
Distinguer une construction en cours d’une reprise nécessaire
Ne pas supprimer l’objet d’une opération encore active
La vue pg_stat_progress_create_index expose les opérations CREATE INDEX et REINDEX en cours, avec leur phase et les objets concernés. Avant d’intervenir sur un état transitoire, faites rapprocher ces informations des sessions et des journaux par l’administrateur. Une photographie isolée du catalogue peut montrer une construction normale qui n’a pas encore terminé.
Dans une application utilisée toute la journée, l’enjeu est de savoir si l’opération avance, attend ou a effectivement échoué. Conservez l’heure de l’observation et le périmètre des droits de lecture. L’absence d’une ligne de progression ne remplace pas l’analyse des logs et de la visibilité disponible. Une automatisation ne devrait pas convertir ce seul constat en ordre de suppression.
Prévoir une attente qui ne ressemble pas à une panne
La création concurrente évite le verrouillage des écritures propre à une construction ordinaire, mais exige davantage de travail et peut attendre des transactions. Elle n’équivaut donc pas à une durée courte ou à une charge négligeable. Fixez une fenêtre d’observation et des conditions d’arrêt à partir de votre environnement, plutôt qu’un délai arbitraire copié d’un autre serveur.
Une longue transaction d’export, un batch ou un worker doit pouvoir être identifié par son responsable. L’objectif n’est pas de tuer toutes les sessions anciennes : certaines exécutent une opération métier indispensable. L’arbitrage doit tenir compte du coût d’attente, de la reprise du traitement et du risque de répéter des effets externes. Cette coordination fait partie de la livraison applicative.
Exemple : huit observations, une seule réception possible
Le contrat d’une liste de commandes ouvertes
Notre exemple fictif demande un index B-tree non unique sur app.commande, avec les clés client_id puis created_at DESC, et le prédicat statut = 'ouverte'. L’équipe exige des résultats corrects et une latence p95 au plus égale à 300 ms sur son protocole de recette. Ce seuil illustratif n’est ni une recommandation PostgreSQL ni une promesse de gain.
Les huit lignes suivantes représentent des observations alternatives du même besoin, pas huit index à créer. Dans la ligne 4, le nom est correct mais le prédicat manque. Dans la ligne 6, la structure est reçue mais le scénario reste trop lent. Dans la ligne 7, la rapidité ne compense pas un résultat métier faux. Les mesures sont inventées pour rendre les décisions vérifiables.
| Cas | État constaté | Décision |
|---|---|---|
| 1. Absent | Aucun objet retrouvé | Préparer la création |
| 2. En cours | Invalide, construction active | Attendre et diagnostiquer |
| 3. Arrêté | Invalide, prêt aux écritures | Qualifier la reprise |
| 4. Autre filtre | Valide, prédicat absent | Traiter l’écart de définition |
| 5. Sans mesure | Structure conforme | Exécuter la recette |
| 6. Trop lent | Résultats corrects, 760 ms | Refuser la performance |
| 7. Résultat faux | 240 ms, résultat incorrect | Refuser la fonction |
| 8. Conforme | Résultats corrects, 240 ms | Recevoir ce scénario |
Trois raccourcis qui donnent un faux feu vert
Le contrôle « le nom existe » accepterait sept lignes. Le contrôle limité à l’état prêt aux écritures en accepterait six ; celui limité à la validité, cinq. Notre règle complète n’en reçoit qu’une. Cette différence ne mesure pas le taux de panne de PostgreSQL : elle montre seulement combien de décisions erronées les critères simplifiés prendraient sur ce jeu construit à cette fin.
Le programme Python téléchargeable réalise 31 contrôles, dont les frontières 299, 300 et 301 ms, les écarts de définition et les mesures manquantes. Il manipule des états normalisés en mémoire, sans connexion PostgreSQL, sans exécution SQL et sans benchmark. Il teste la politique de réception ; une répétition sur votre environnement doit encore vérifier le comportement réel de la base.
La fonction reçoit en entrée un contrat normalisé et des observations déjà qualifiées. Sa sortie distingue notamment ECART_DEFINITION, REPRISE_A_QUALIFIER, MESURER et RECEVOIR. Une valeur de mesure manquante impose MESURER ; elle ne devient pas zéro. Pour intégrer cette logique à votre outillage, séparez la collecte PostgreSQL, la normalisation et la décision. Le programme ne parse pas une définition SQL et ne remplace aucun de ces contrôles de collecte.
python3 controle_index.py
# 8 observations alternatives
# 31 contrôles ; 3 critères insuffisants réfutés
# Aucun accès base, aucune création ou suppression d’index
Choisir la reprise à partir de l’objet réellement trouvé
Reconstruire une bonne définition ou corriger une mauvaise
La documentation REINDEX prévoit la reconstruction d’un index invalide et précise que seule la forme REINDEX INDEX peut effectuer sa reconstruction concurrente. Cela ne signifie pas que toute situation appelle cette commande : si la définition est incorrecte, reconstruire le même objet ne répondra pas au contrat attendu. L’écart doit être identifié avant le choix de procédure.
Une procédure préparée peut retenir une reconstruction ou une suppression suivie d’une nouvelle création, selon l’objet et ses dépendances. Documentez le nom qualifié, l’identité observée, la définition voulue, les conditions préalables et les contrôles après exécution. Faites relire le plan par l’équipe responsable de la base. Un script de reprise ne doit pas deviner une action destructive à partir du seul suffixe d’un nom.
Évaluer ce que la suppression retire réellement
La référence DROP INDEX distingue les verrous de la suppression ordinaire et les attentes de sa variante concurrente. Cette dernière comporte des restrictions, notamment sur les index qui soutiennent une contrainte UNIQUE ou PRIMARY KEY, les index partitionnés et l’exécution dans une transaction. Une commande générique de nettoyage ne peut pas ignorer ces différences.
Pour un index unique invalide, demandez aussi quelle protection reste active et ce qui se passera pendant l’intervalle de correction. Réouvrir sans cette analyse peut laisser entrer des données que la reconstruction suivante refusera. Le responsable des données doit arbitrer les doublons éventuels, tandis que l’équipe applicative précise les écritures autorisées et la stratégie de reprise des demandes temporairement refusées.
Intégrer la postcondition dans une migration Symfony et Doctrine
Rendre explicite le contexte transactionnel
CREATE INDEX CONCURRENTLY ne s’exécute pas dans un bloc de transaction. De son côté, Doctrine Migrations 3.9 documente isTransactional(), vrai par défaut, et la possibilité de le redéfinir. Vérifiez la version installée, la configuration d’exécution et une éventuelle enveloppe transactionnelle ajoutée par vos scripts avant de préparer cette migration.
Ne désactivez pas les transactions de tout le lot pour contourner une seule commande. Isolez l’étape qui l’exige, décrivez ce qui peut rester après un échec et prévoyez une reprise adaptée. Dans une application Symfony, le fichier de migration, la commande réellement lancée et le job CI doivent être relus ensemble. Un commentaire PHP ne prouve pas le contexte d’exécution final.
Faire échouer clairement une livraison incomplète
Après l’étape de construction, un contrôle doit distinguer absent, définition différente, opération encore active et état attendu. Si la postcondition n’est pas établie, le déploiement doit conserver un statut explicite qui empêche de déclarer la correction reçue. L’équipe peut choisir une vérification séparée de la migration, à condition qu’elle soit obligatoire dans le processus de livraison.
La table d’historique des migrations n’est pas un inventaire exhaustif des propriétés physiques. Elle aide à comprendre les actions déclarées, mais une modification manuelle ou une relance mal qualifiée peut créer un écart. Conservez les observations de catalogue avec le journal de livraison et l’identifiant du changement. Cette traçabilité réduit le travail de diagnostic lorsque le support retrouve la lenteur plusieurs jours plus tard.
Confiez la responsabilité du contrôle à une étape nommée de la livraison. Sa journalisation doit conserver la base, le schéma, l’identité de l’objet, les états relevés, la définition comparée et l’heure de lecture, sans exposer de données client. Pour assurer la traçabilité, associez ce relevé au commit livré et à la recette attendue. Un résultat MESURER reste une étape ouverte ; seul le responsable de réception peut conclure après ajout des observations manquantes.
Recevoir la recherche, pas seulement l’état de l’index
Interpréter le plan avec les paramètres du parcours
EXPLAIN aide à lire le plan choisi ; EXPLAIN ANALYZE exécute la requête et ajoute des observations réelles. Préparez son usage avec la charge et les effets de la requête en tête. Un parcours de lecture représentatif peut être étudié sans transformer une commande d’écriture métier en test improvisé sur la production.
Un parcours séquentiel n’est pas automatiquement une anomalie : la sélectivité, le volume et les coûts influencent le choix du planificateur. Ne forcez pas artificiellement un index pour obtenir une capture rassurante. Comparez des paramètres représentatifs, les résultats attendus et un protocole stable. La conclusion doit expliquer le service rendu, pas simplement afficher le nom de l’index dans un plan.
Mesurer le coût visible et le coût de support
Dans une hypothèse de travail, 18 gestionnaires effectuent chacun 40 recherches par jour. Une attente supplémentaire de 1,5 seconde représente 1 080 secondes cumulées, soit 19 minutes quotidiennes. Ce calcul ne devient pas automatiquement un gain de productivité : les attentes peuvent se chevaucher et les utilisateurs peuvent faire autre chose. Il sert à dimensionner l’enquête, avec des hypothèses affichées.
Ajoutez les tickets, les relances et les exports de contournement réellement constatés avant de décider d’un investissement. Vérifiez aussi l’effet de la construction sur les écritures et les traitements différés. Une amélioration de la liste qui dégrade la saisie ou ralentit un flux CRM n’est pas une réception complète. La QA doit couvrir les usages exposés par cette modification.
Erreurs fréquentes : relancer sans définir ce qui doit être vrai
- À faire : conserver l’erreur initiale, vérifier l’objet et relier sa définition à la requête ciblée.
- À différer : la clôture tant que l’état final et la recette du parcours ne sont pas établis.
- À refuser : la suppression automatique d’un index uniquement parce que son nom ressemble à un résidu.
Confondre reprise technique et retour fonctionnel
Un retour à l’ancienne version du code n’annule pas automatiquement toutes les étapes déjà exécutées dans la base. Si la migration est partiellement appliquée, la procédure de retour doit décrire cette situation. Vérifiez la compatibilité de l’ancien code avec l’état restant, puis distinguez ce qui doit être conservé, réparé ou retiré. Un bouton de relance du pipeline ne porte pas cette analyse à lui seul.
Évitez également d’ajouter un second index proche pour calmer l’incident sans inventorier le premier. Deux objets presque équivalents peuvent compliquer l’exploitation et les futures migrations. La décision doit conserver la raison du choix et le périmètre de vérification. Le retour au service est plus facile à expliquer lorsque chaque objet a une fonction claire dans l’architecture.
Remplacer les preuves par une accumulation de compteurs
Le nombre d’index ou le nombre de lignes ne répond pas à la question de leur adéquation. Notre exemple garde un nom cohérent dans sept observations et n’en reçoit qu’une. De même, une mesure globale de latence peut cacher un filtre lent sur les clients volumineux. Choisissez les dimensions qui distinguent les situations importantes, plutôt que de multiplier des chiffres sans décision associée.
La surveillance après livraison doit reprendre ces dimensions : parcours, paramètres représentatifs, erreurs et observations de charge. Un seuil dépassé doit conduire à un responsable et à une action précise. Sinon, l’observabilité produit une alerte supplémentaire sans raccourcir la résolution. Le support doit pouvoir retrouver le changement concerné et la preuve qui avait justifié son acceptation.
Plan d’action : inspecter, répéter, puis recevoir un périmètre limité
Commencez par un dossier de diagnostic restreint : version PostgreSQL, base et schéma, migration, erreur initiale, requête ciblée et observations actuelles. Désignez une personne pour l’application et une pour la base. Leur première décision consiste à confirmer qu’elles examinent le même objet et le même besoin, sans modifier l’état simplement pour faire disparaître un avertissement du journal.
Préparez ensuite la reprise sur un environnement représentatif. Définissez les données et dépendances à protéger, la fenêtre disponible, les critères d’arrêt et la compatibilité avec le code servi. La répétition doit comprendre un échec volontaire maîtrisé ou un état incomplet reproduit dans ce périmètre de test, afin de vérifier que la procédure distingue bien une relance d’une réparation.
Ouvrez un pilote lorsque la définition et les états attendus sont établis, puis exécutez les recherches et écritures prévues dans la recette. Comparez les résultats avant d’interpréter les durées. Si les accès de diagnostic sont insuffisants, si une opération est encore active ou si les mesures ne sont pas représentatives, différez l’acceptation et indiquez l’information manquante au lieu de choisir une correction par défaut.
Terminez par un relevé daté des postconditions, de la recette et des limites restantes. Confiez le suivi à un responsable identifié avec une fenêtre d’observation adaptée au rythme des utilisateurs. Une base peu sollicitée le week-end peut ne révéler son comportement métier qu’au prochain cycle de travail. La clôture doit donc distinguer la correction appliquée, le pilote reçu et la confirmation en usage courant.
Prolonger la vérification jusqu’au déploiement métier
Répéter la bascule avec ses conditions de reprise
La répétition générale d’une migration permet de préparer les gestes, les dépendances et les décisions qui dépassent un index particulier. Utilisez-la lorsque la construction s’insère dans un changement plus large de données ou d’application, avec plusieurs équipes et une fenêtre de bascule commune.
Le diagnostic présent fournit alors un contrôle ciblé à intégrer à cette répétition. Il ne remplace ni la restauration éprouvée ni la coordination des écritures. Le résultat utile est une procédure que l’équipe peut exécuter et interrompre avec des critères compris, y compris lorsque l’état rencontré diffère de celui attendu au départ.
Conserver les preuves dans l’environnement du client
Le déploiement d’un logiciel dans le SI du client pose la question des accès, des responsabilités et des validations disponibles sur la cible. Une migration vérifiée ailleurs doit encore être reliée au serveur, aux droits et au mode d’exploitation réellement retenus pour l’application.
Transmettez au support les observations utiles sans lui demander de reconstruire toute l’enquête. Le dossier peut rester court : définition attendue, état reçu, parcours testé, procédure de diagnostic et personne responsable. Cette continuité entre livraison et maintenance évite que l’incident suivant reparte uniquement d’un écran lent et d’un ancien job vert.
Conclusion : recevoir une propriété vérifiée, pas un nom existant
Un index présent n’atteste ni sa validité, ni la conformité de sa définition, ni le résultat obtenu par l’application. Après une construction concurrente interrompue, la reprise doit partir des observations de catalogue et de l’activité réelle. Elle se termine par une postcondition et une recette, pas par la disparition d’un message d’erreur.
L’exercice à huit observations rend cette distinction concrète : sept noms présents, cinq états valides et une seule réception selon les critères choisis. Ses 31 contrôles éprouvent une décision locale ; ils ne constituent pas un test du moteur PostgreSQL. La preuve de votre installation vient de la répétition et des mesures conduites sur son propre périmètre.
Un audit technique de votre application web peut rapprocher les migrations, les requêtes lentes et les preuves de livraison pour définir ce qui doit être corrigé en priorité. La décision devient plus précise lorsque chaque symptôme est associé à un objet, un usage et une condition d’acceptation observable.
Dawap accompagne le développement web sur mesure en intégrant les contraintes de données et d’exploitation aux évolutions du logiciel. Nous aidons vos équipes à cadrer la correction, préparer sa reprise et recevoir le parcours métier, afin que le déploiement terminé corresponde à un changement effectivement compris et vérifié.