Se rendre au contenu

Champ Indexé dans Odoo : Guide Pratique pour Développeurs et Consultants

Comprendre l’attribut index dans l’ORM d’Odoo et son impact sur les performances de votre base de données
6 mars 2026 par
Champ Indexé dans Odoo : Guide Pratique pour Développeurs et Consultants
Dasolo
| Aucun commentaire pour l'instant

Introduction


Si vous avez déjà parcouru des définitions de champs Odoo, vous avez sûrement remarqué parfois la présence de index=True. Ce petit attribut semble anodin, mais il change la façon dont PostgreSQL retrouve des enregistrements et peut transformer l’expérience utilisateur quand les volumes de données augmentent.


Ce guide explique, de manière opérationnelle, ce que signifie réellement indexer un champ dans le modèle de données d’Odoo, quelles conséquences cela a au niveau de la base et à quelles occasions il est pertinent d’y recourir lors du développement de modules ou de l’optimisation d’une instance.

Qu’est-ce qu’un champ indexé dans Odoo


Dans l’ORM d’Odoo, on marque un champ comme indexé en ajoutant index=True à sa déclaration Python. Concrètement, Odoo demandera à PostgreSQL de créer un index sur la colonne correspondante au moment de l’installation ou de la mise à jour du module.


Exemple simple d’une définition de champ dans un module Python :

class SaleOrder(models.Model):
    _name = 'sale.order'

    reference = fields.Char(string='Reference', index=True)
    state = fields.Selection([...], index=True)
    partner_id = fields.Many2one('res.partner', index=True)

Pour l’utilisateur final, rien ne change visuellement : un champ indexé n’a pas d’indicateur particulier dans les formulaires ou listes. L’indexation est une optimisation côté base de données uniquement.


L’intérêt principal est la vitesse. Un index permet à PostgreSQL de localiser rapidement les lignes correspondantes sans parcourir toute la table — ce qui devient crucial dès que les tables comptent des milliers ou millions d’enregistrements. Sans index, la base effectue un scan séquentiel ; avec index, elle remonte directement aux résultats via une structure triée.


Quels types de champs Odoo acceptent index=True

La plupart des champs scalaires de l’ORM supportent l’attribut index :

  • Char et Text
  • Integer et Float
  • Date et Datetime
  • Selection
  • Many2one (très souvent indexés par défaut)
  • Boolean

En revanche, les champs relationnels comme One2many ou Many2many n’ont pas de colonne simple à indexer, donc l’attribut index n’est pas pertinent. De même, les champs calculés non stockés ne peuvent pas être indexés puisqu’ils n’ont pas de colonne physique en base.

Comment fonctionne ce champ


Lors de l’initialisation ou de la montée de version d’un module, Odoo synchronise les définitions de champs avec le schéma PostgreSQL. Pour chaque champ portant index=True, Odoo exécute la commande SQL nécessaire pour créer l’index sur la colonne correspondante.


Par défaut PostgreSQL crée un index B-tree — adapté aux comparaisons d’égalité, aux plages (>, <, BETWEEN) et au tri. Ce type couvre la majorité des opérations de filtrage et d’ordonnancement que réalise Odoo dans les vues et domaines.


Interaction avec l’ORM Odoo

L’ORM traduit les domaines Python en requêtes SQL. Un domaine tel que [('state', '=', 'sale')] devient un WHERE state = 'sale'. Si le champ state est indexé, PostgreSQL peut utiliser l’index pour extraire rapidement les lignes correspondantes sans parcourir toute la table.


Les Many2one illustrent bien l’usage courant : un champ partner_id stocke l’ID entier du partenaire. Filtrer les commandes par client produit un WHERE partner_id = X. Avec un index sur partner_id, cette recherche reste rapide même avec des centaines de milliers de commandes.


Impact sur les écritures

Les index ont un coût : à chaque insertion, mise à jour ou suppression, PostgreSQL doit mettre à jour tous les index de la table. Plus une table a d’index, plus les opérations d’écriture deviennent lentes. Dans la plupart des cas Odoo, le compromis lecture/écriture penche en faveur de l’indexation, mais indexer systématiquement tous les champs est une mauvaise pratique.

L’option index='trigram'

À partir d’Odoo 16, index peut valoir 'trigram'. Cela crée un index trigramme (GIN) via l’extension pg_trgm, optimisé pour les correspondances de motifs (ILIKE). Utile pour la recherche partielle sur des noms de produits, de partenaires ou tout champ texte souvent cherché par fragments.


name = fields.Char(string='Product Name', index='trigram')

C’est une option avancée déjà employée dans les modules standards d’Odoo pour les champs soumis à des recherches par sous-chaînes fréquentes.

Cas d’usage en entreprise


Exemples concrets d’utilisation


1. CRM : filtrer les opportunités par commercial

Les managers CRM filtrent régulièrement le pipeline par commercial. Le champ user_id sur crm.lead est indexé dans Odoo pour garantir des filtres rapides même avec des milliers d’opportunités. Le raisonnement est identique pour tout Many2one personnalisé pointant vers un utilisateur ou une équipe.


2. Ventes : rechercher les commandes par statut

Le champ state sur sale.order est indexé, ce qui rend les vues filtrées par statut très réactives pour les entreprises à fort volume. Les champs de type selection utilisés comme filtres sont de bons candidats à l’indexation.


3. Stock : suivre les mouvements par produit

Les mouvements de stock peuvent atteindre des volumes considérables. L’indexation du product_id sur stock.move permet d’extraire rapidement l’historique d’un produit. Sans cet index, les rapports de traçabilité deviennent très lents dans les entrepôts actifs.


4. Comptabilité : consulter les écritures par tiers

Les comptables consultent fréquemment le grand livre pour un fournisseur ou client. L’index sur partner_id dans account.move.line accélère ces recherches et empêche les rapports âgés de créances de dépasser les limites de temps dans des bases historiques.


5. Modules personnalisés : champs de référence pour traçabilité

Dans les développements sur mesure, on ajoute souvent des champs référence (code projet, numéro externe). Si ces champs servent aux recherches quotidiennes, il est logique d’y appliquer index=True pour garantir des performances prévisibles à mesure que le volume de données augmente.


Créer ou personnaliser un champ indexé


En Python (développement de module)

Déclarer index=True dans un module Python est simple : il suffit d’ajouter l’argument lors de la définition du champ.


from odoo import models, fields

class ProjectTask(models.Model):
    _inherit = 'project.task'

    x_external_ref = fields.Char(
        string='External Reference',
        index=True,
        help='Reference number from the external system'
    )

Après avoir modifié le code, mettez à jour le module avec odoo-bin -u your_module_name ou via l’interface Apps. Odoo détectera le nouveau champ et créera l’index en base lors de l’upgrade.


Il est aussi possible d’ajouter un index sur un champ existant en l’héritant et en redéfinissant sa déclaration, mais cette méthode demande prudence pour ne pas altérer involontairement le comportement original du champ.


Avec Odoo Studio

Odoo Studio permet aux non-développeurs de créer des champs depuis l’interface, mais il n’expose pas d’option pour activer l’indexation. Les champs créés via Studio ne sont pas indexés par défaut.


Si la performance exige l’indexation d’un champ Studio, la solution la plus propre consiste à transformer la personnalisation en module Python et à y ajouter index=True. Cela nécessite l’intervention d’un développeur Odoo.


Créer un index directement en PostgreSQL

Pour optimiser une base en production sans passer par une montée de version, un DBA peut créer l’index manuellement via SQL :

CREATE INDEX CONCURRENTLY idx_sale_order_partner_id
ON sale_order (partner_id);

L’option CONCURRENTLY permet d’éviter le verrouillage de la table pendant la création — crucial en production. Toutefois, il faut coordonner cette action avec les définitions de modules pour éviter des divergences entre le code et le schéma si l’on réapplique un upgrade à l’avenir.


Bonnes pratiques


Indexer les champs utilisés dans les domaines de recherche

Si un champ apparaît fréquemment dans des domaines (filtres de liste, actions automatisées, jobs programmés ou dépendances de champs calculés), il mérite qu’on envisage de l’indexer. Les Many2one, champs d’état et champs de référence/code sont des exemples typiques.


Suivre les conventions d’Odoo

Les définitions de champs standards d’Odoo sont une excellente source d’indications : consultez sale.order, account.move ou stock.move pour voir quels champs sont indexés. Ces choix reflètent des patterns d’utilisation réels sur de nombreuses bases en production.


Toujours indexer les Many2one sur les modèles à fort volume

Sur les modèles qui accumulent beaucoup d’enregistrements (écritures comptables, mouvements de stock, lignes de commande), il est généralement judicieux d’indexer les Many2one utilisés pour filtrer. Le surcoût sur les écritures est souvent compensé par le gain en lecture.


Envisager l’index trigramme pour la recherche texte

Sur Odoo 16+, si les utilisateurs recherchent souvent par fragments dans des champs Char (nom produit, partenaire, référence), préférez index='trigram' plutôt que le B-tree classique. Les trigrammes sont optimisés pour les recherches ILIKE partielles.


Vérifier que l’index est effectivement utilisé

Après création, testez avec un EXPLAIN ANALYZE pour confirmer que PostgreSQL utilise l’index. Si le plan choisi reste un sequential scan, soit la table est trop petite pour que l’index soit utile, soit les conditions de requête ne conviennent pas au type d’index.


Documenter vos choix d’indexation

Laissez un commentaire dans le code qui explique pourquoi un champ est indexé. Cela aide les équipes futures à comprendre l’intention et évite la suppression accidentelle d’un index lors d’un refactor.

Pièges fréquents


Indexer tous les champs par défaut

Erreur courante : ajouter index=True systématiquement. Chaque index occupe de l’espace disque et ralentit les écritures. Sur les tables à forte activité d’insertion ou de mise à jour, les index superflus peuvent dégrader les performances globales.


Indexer des tables petites ou peu remplies

Sur des tables de quelques centaines de lignes, le planner favorise souvent le scan séquentiel. L’index n’apporte un bénéfice réel qu’à partir de plusieurs milliers d’enregistrements. Indexer des tables de lookup ou des modèles rarement remplis complique inutilement le schéma.


Oublier d’upgrader le module après avoir ajouté index=True

Ajouter index=True dans le code ne crée pas automatiquement l’index en base si vous oubliez d’upgrader le module. Lancer -u module_name ou passer par l’interface est nécessaire ; oublier ce passage est une source fréquente de confusion.


S’attendre à des gains pour les recherches ILIKE classiques

Un index B-tree ne sert pas pour les requêtes ILIKE '%terme%' où le joker est placé en début de motif. PostgreSQL ne peut pas utiliser un B-tree pour un joker initial. Pour des recherches partielles rapides, utilisez index='trigram' ou explorez la recherche en texte intégral.


Ne pas penser aux champs calculés stockés

Les champs calculés avec store=True créent une colonne en base et peuvent donc être indexés. Les oublier est une opportunité manquée : si un champ stocké est souvent utilisé dans des domaines, l’indexation peut grandement améliorer les performances.

Conclusion


L’attribut index=True est un détail de déclaration, mais il a un réel impact à mesure que vos données croissent. Bien appliqué, il maintient les recherches et rapports réactifs ; mal appliqué, il alourdit les écritures et le stockage sans bénéfice.


En résumé : indexez les champs régulièrement employés dans les domaines, en particulier les Many2one sur les modèles volumineux. Inspirez-vous des choix effectués dans les modules standards d’Odoo. Évitez l’indexation systématique des petites tables et, si vous êtes sur Odoo 16+, pensez à index='trigram' pour la recherche texte partielle.


Il est bien plus simple de définir une stratégie d’indexation correcte dès le départ d’un projet que d’essayer de dénouer des requêtes lentes en production plus tard.

Vous travaillez sur une implémentation Odoo ?


Chez Dasolo, nous accompagnons les entreprises pour implémenter, personnaliser et optimiser Odoo. Que ce soit pour développer des modules sur mesure, améliorer les performances d’une instance existante ou concevoir une nouvelle solution, nous apportons une expertise technique pratique à chaque mission.


Si vous rencontrez des requêtes lentes, des personnalisations complexes, ou si vous souhaitez des conseils sur les bonnes pratiques de développement Odoo, nous pouvons vous accompagner. Contactez l’équipe Dasolo et dites-nous sur quel projet vous travaillez.

Champ Indexé dans Odoo : Guide Pratique pour Développeurs et Consultants
Dasolo 6 mars 2026
Partager cet article
Se connecter pour laisser un commentaire.