Introduzione
Se hai mai scritto o rivisto definizioni di campi in Odoo, avrai notato l’aggiunta apparentemente innocua index=True. È una piccola istruzione nel codice, ma può cambiare radicalmente la reattività del sistema quando gli utenti filtrano, cercano o navigano grandi moli di dati.
Questo articolo spiega in parole semplici cosa succede quando un campo è indicizzato nel modello dati di Odoo, quali effetti ha sul database e in quali scenari ha senso inserirlo durante lo sviluppo. Che tu stia costruendo un modulo personalizzato o valutando un sistema esistente, capire questo concetto ti aiuta a prendere decisioni più efficaci e sostenibili nel tempo.
Che cos’è un campo indicizzato in Odoo
Nel framework ORM di Odoo, un campo diventa indicizzato quando nella sua dichiarazione Python è presente index=True. Questo indica ad Odoo di chiedere a PostgreSQL di creare un indice sul campo corrispondente al momento dell’installazione o dell’aggiornamento del modulo.
Per rendere l’idea:
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)
Dal punto di vista dell’interfaccia utente non cambia nulla: chi compila una scheda o scorre una lista non vede alcuna etichetta che indichi “campo indicizzato”. L’indicizzazione è una caratteristica che agisce esclusivamente a livello di storage, nel database sottostante.
Dove si vede davvero la differenza è nelle prestazioni. Un campo indicizzato permette a PostgreSQL di trovare i record corrispondenti molto più rapidamente, soprattutto quando le tabelle contengono decine di migliaia o milioni di righe. Senza indice il motore deve eseguire una scansione completa della tabella; con l’indice sfrutta una struttura ordinata per arrivare subito ai record rilevanti.
Quali tipi di campo Odoo supportano index=True
In linea generale i tipi scalari dell’ORM Odoo supportano l’attributo index:
- Campi Char e Text
- Campi Integer e Float
- Campi Date e Datetime
- Campi Selection
- Campi Many2one (tra i più frequentemente indicizzati)
- Campi Boolean
Campi relazionali come One2many e Many2many non corrispondono a una singola colonna nel modo in cui lo fa un Many2one, quindi l’attributo index non si applica direttamente. Anche i campi computati che non sono memorizzati (non stored) non hanno una colonna su cui creare un indice.
Come funziona il campo
Quando Odoo installa o aggiorna un modulo legge le definizioni dei campi e allinea lo schema del database. Per ogni campo con index=True, Odoo esegue la query SQL necessaria a creare l’indice sulla colonna interessata in PostgreSQL.
Per impostazione predefinita PostgreSQL crea un indice di tipo B-tree: è il più comune e funziona bene per confronti di uguaglianza (=), range (>, <, BETWEEN) e ordinamenti. Sono proprio queste le operazioni che Odoo esegue più spesso quando filtra liste o applica domini.
Interazione con l’ORM di Odoo
L’ORM traduce i domini Python in query SQL. Un dominio come [('state', '=', 'sale')] diventa un WHERE state = 'sale'. Se il campo state è indicizzato, PostgreSQL può risolvere la condizione utilizzando l’indice invece di leggere tutte le righe della tabella.
Un caso tipico è il campo Many2one. Su una vendite, il campo partner_id memorizza l’ID numerico del partner. Quando si filtrano gli ordini per cliente, la query contiene WHERE partner_id = X; con l’indice su partner_id la ricerca resta veloce anche con centinaia di migliaia di ordini.
Indici e prestazioni in scrittura
Gli indici non sono gratuiti: a ogni inserimento, aggiornamento o cancellazione PostgreSQL deve aggiornare anche gli indici della tabella. Su tabelle con molti indici le operazioni di scrittura diventano più lente. Nella maggior parte dei casi il compromesso è accettabile, ma indicizzare tutto indiscriminatamente non è una strategia corretta.
L’opzione index='trigram'
Da Odoo 16 in poi l’attributo index può assumere anche la stringa 'trigram'. Questo crea un indice GIN basato su trigrammi (richiede l’estensione pg_trgm), pensato per velocizzare ricerche testuali con ILIKE e corrispondenze parziali. Utile per campi come nomi prodotto o anagrafiche dove l’utente cerca per frammento di testo.
Un esempio pratico: name = fields.Char(string='Product Name', index='trigram')
È una scelta avanzata che Odoo utilizza sui campi frequentemente cercati con testo parziale e che migliora molto l’esperienza di ricerca rispetto al semplice B-tree per questi scenari.
Quando conviene usarlo in azienda
Esempi pratici in cui l’indicizzazione fa la differenza
1) CRM: filtrare i lead per commerciale
Nei CRM i responsabili filtrano spesso il funnel per proprietario. Il campo user_id su crm.lead è indicizzato di default, così anche con migliaia di lead il filtro rimane immediato. Lo stesso vale per eventuali campi Many2one personalizzati verso utenti o team: se li usi nei filtri, indicizzali.
2) Vendite: cercare ordini per stato
Il campo state su sale.order è indicizzato: questo permette di caricare liste di ordini confermati o in attesa di consegna in modo rapido anche su volumi elevati. In generale le selection usate frequentemente come criteri di filtro sono buone candidate per l’indice.
3) Magazzino: tracciare movimenti per prodotto
I movimenti di magazzino possono diventare moltissimi in attività logistiche o produttive. Avere product_id indicizzato su stock.move rende rapide le interrogazioni sui movimenti di un prodotto; senza indice i report di tracciabilità sarebbero lenti o inutilizzabili in magazzini molto attivi.
4) Contabilità: estrarre le righe per cliente/fornitore
Gli addetti alla contabilità consultano spesso la partita aperta per un cliente o un fornitore. La presenza di partner_id indicizzato su account.move.line mantiene veloci queste ricerche anche su storici pluriennali, evitando timeout nei report di scadenze e bilanci.
5) Moduli personalizzati: campi di riferimento per tracciabilità
Nei moduli custom è comune aggiungere codici di riferimento o numeri esterni. Se gli utenti cercano regolarmente per questi riferimenti, impostare index=True sui campi coinvolti è la soluzione più semplice per mantenere le prestazioni con l’aumentare dei dati.
Creare o personalizzare un campo indicizzato
In Python (sviluppo di moduli)
Dichiarare index=True in un modulo Python è immediato: basta aggiungerlo come argomento del campo al momento della definizione.
Esempio pratico: 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'
)
Dopo aver aggiunto il campo aggiorna il modulo con odoo-bin -u your_module_name o tramite la UI Apps. Odoo individuerà il nuovo campo e creerà l’indice corrispondente nel database.
È possibile anche indicizzare un campo esistente sovrascrivendone la definizione con un’eredità (inherit), ma bisogna fare attenzione per non alterare inavvertitamente il comportamento originale del campo.
In Odoo Studio
Odoo Studio consente agli utenti non tecnici di aggiungere campi via interfaccia, ma al momento non espone l’opzione per attivare l’indicizzazione. I campi creati con Studio non hanno index=True di default e restano campi gestiti manualmente nel database.
Se serve indicizzare un campo creato con Studio per motivi di performance, la strada più pulita è trasformare la personalizzazione in un modulo Python e aggiungere l’indice in codice. Questa operazione richiede competenze tecniche e viene solitamente svolta da sviluppatori Odoo.
Aggiungere un indice direttamente in PostgreSQL
In alcuni casi, per ottimizzare un database di produzione senza aggiornare il modulo, un DBA può creare l’indice direttamente con SQL.
Esempio SQL: CREATE INDEX CONCURRENTLY idx_sale_order_partner_id
ON sale_order (partner_id);
L’opzione CONCURRENTLY evita di bloccare la tabella durante la creazione dell’indice — fondamentale su sistemi in produzione. Tuttavia, è importante coordinare questa operazione con la definizione del modulo in Odoo per mantenere il codice e lo schema sincronizzati; un upgrade futuro del modulo potrebbe gestire l’indice in modo diverso.
Buone pratiche
Indicizzare i campi usati nei domini di ricerca
Se un campo è frequentemente impiegato nei filtri (liste, azioni automatiche, job schedulati o dipendenze di campi computati), è un buon candidato per l’indice. In pratica i Many2one, i campi stato e i campi di riferimento/codice sono quelli che tipicamente ne beneficiano di più.
Segui le convenzioni di Odoo
Un ottimo metro di giudizio è osservare cosa fa Odoo nel suo core. Analizza le definizioni standard in moduli come sale.order, account.move o stock.move: i campi che Odoo ha scelto di indicizzare riflettono pattern d’uso reali e dati di performance raccolti in migliaia di installazioni.
Indicizza sempre i Many2one su modelli ad alto volume
Per i modelli che accumulano molte righe nel tempo (movimenti di magazzino, voci di diario, righe d’ordine), è buona norma indicizzare i Many2one usati per i filtri. Il costo aggiuntivo sulle scritture è quasi sempre compensato dal miglioramento delle letture.
Valuta l’indice trigram per ricerche testuali
Se gli utenti cercano per frammenti di testo in campi Char (nomi prodotto, anagrafiche, riferimenti), su Odoo 16+ valuta index='trigram'. Gli indici trigram accelerano molto le ricerche con ILIKE e pattern parziali.
Verifica che l’indice venga effettivamente usato
Dopo aver creato un indice, controlla con EXPLAIN ANALYZE che PostgreSQL lo stia sfruttando. Se il planner sceglie ancora una scansione sequenziale, la tabella potrebbe essere troppo piccola per giustificare l’indice o la query non essere compatibile col tipo d’indice scelto.
Documenta perché hai aggiunto un indice
Quando sviluppi un modulo, lascia un breve commento che spieghi il motivo per cui un campo è indicizzato. Questo aiuta chi lavora in futuro a capire l’intento e a non rimuovere l’indice accidentalmente durante una ristrutturazione del codice.
Errori comuni
Indicizzare tutto per sicurezza: un errore comune
Un errore ricorrente è impostare index=True su tutti i campi “per sicurezza”. Questo è controproducente: ogni indice occupa spazio e rallenta le scritture. Su tabelle con elevato volume di insert/update gli indici inutili possono degradare significativamente le prestazioni.
Indicizzare tabelle piccole
Su tabelle con poche centinaia di righe il planner di PostgreSQL spesso preferisce la scansione sequenziale: in questi casi l’indice non porta benefici pratici. Evita di aggiungere indici a lookup table o modelli custom poco popolati.
Dimenticare l’upgrade del modulo dopo aver aggiunto index=True
Aggiungere index=True nel codice non crea automaticamente l’indice finché il modulo non viene aggiornato con -u module_name o tramite backend. Dimenticare questo passaggio è una fonte comune di confusione in fase di sviluppo e può portare a problemi di performance in staging o produzione.
Aspettative sbagliate sulle ricerche ILIKE
Un indice B-tree non accelera ricerche del tipo ILIKE '%parola%' con wildcard iniziale: PostgreSQL non può usare B-tree per pattern con wildcard all’inizio. Per ricerche parziali serve index='trigram' su Odoo 16+ o soluzioni di full-text search.
Non considerare i campi computati memorizzati
I campi computati con store=True scrivono una colonna nel database e possono essere indicizzati. Spesso gli sviluppatori trascurano questa possibilità; se un campo memorizzato viene usato regolarmente nei filtri, indicizzarlo può migliorare molto le prestazioni.
Conclusione
Il bilancio finale
L’attributo index=True è un dettaglio piccolo nella definizione di un campo, ma ha un impatto concreto sulle prestazioni man mano che i dati crescono. Usato correttamente mantiene veloci le ricerche, le viste elenco e i report; usato senza criterio aggiunge overhead senza valore. Indica i campi che compaiono nei domini, soprattutto i Many2one su modelli affollati, segui le scelte del core Odoo e valuta index='trigram' per le ricerche testuali su Odoo 16+.
È molto più semplice progettare una strategia di indicizzazione corretta all’inizio di un progetto che diagnosticare query lente in produzione dopo che i dati sono cresciuti.
Stai lavorando a un’implementazione Odoo?
Da parte nostra, in Dasolo affianchiamo le aziende nell’implementazione, personalizzazione e ottimizzazione di Odoo. Che tu stia sviluppando moduli custom, cercando di velocizzare un’istanza esistente o pianificando un nuovo progetto, portiamo competenze tecniche pratiche a ogni incarico.
Se ti trovi davanti a query lente, personalizzazioni complesse o vuoi una revisione delle best practice di sviluppo Odoo, possiamo supportarti. Contatta il team Dasolo e raccontaci il progetto su cui stai lavorando.