Inleiding
Wanneer u Odoo-code bekijkt, ziet u vaak iets kleins maar impactvols: index=True bij een velddefinitie. Het lijkt een detail, maar eenmaal aanwezig kan het bepalen of zoekacties en filters vlot verlopen of traag aanvoelen wanneer de data groeit.
Deze handleiding legt helder uit wat een geïndexeerd veld betekent binnen het Odoo-datamodel, wat er in de database gebeurt en wanneer u het best indexering gebruikt in eigen ontwikkelwerk. Of u nu een module bouwt of bestaand werk evalueert: dit inzicht helpt u betere keuzes te maken.
Wat betekent een geïndexeerd veld in Odoo?
In de Odoo ORM geef je een veld als geïndexeerd op door index=True in de definities mee te geven. Daarmee vraagt Odoo bij installatie of upgrade aan PostgreSQL om een index op de corresponderende kolom aan te maken.
Hiermee wordt het idee geïllustreerd met een eenvoudig voorbeeld van zo’n velddefinitie in 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)
Voor eindgebruikers verandert er niets aan de vorm of weergave: indexering is een technische, database‑gerichte optimalisatie. In formulieren of lijstweergaven zien gebruikers niet of een veld geïndexeerd is.
De echte impact zit in snelheid. Met een index kan PostgreSQL gericht records opzoeken via een gesorteerde structuur in plaats van elke rij te moeten doorzoeken. Dat scheelt enorm op tabellen met duizenden of miljoenen rijen.
Welke Odoo-veldtypes ondersteunen index=True
De meeste eenvoudige (scalaire) veldtypes in Odoo kunnen worden geïndexeerd met het index-attribuut.
- Char‑ en Text‑velden
- Integer‑ en Float‑velden
- Date‑ en Datetime‑velden
- Selection‑velden
- Many2one‑velden (veelal geïndexeerd)
- Boolean‑velden
Relaties zoals One2many en Many2many hebben geen eigen kolom om op te indexeren, dus index is daar niet van toepassing. Ook berekende velden zonder opslag (store=False) hebben geen fysieke kolom en kunnen niet geïndexeerd worden.
Hoe het veld precies werkt
Bij module‑installatie of -upgrade synchroniseert Odoo velddefinities met het databaseschema. Voor elk veld met index=True voert Odoo een SQL‑commando uit om in PostgreSQL een index aan te maken op de betreffende kolom.
Standaard maakt PostgreSQL een B‑tree index, de gebruikelijke indexvorm die goed werkt voor gelijkheidschecks (=), bereikqueries (>/<, BETWEEN) en sorteren — precies wat de meeste Odoo‑filters en domains gebruiken.
Hoe dit samenwerkt met de Odoo ORM
De ORM vertaalt Python‑domains naar SQL. Een domain als [('state', '=', 'sale')] resulteert in een WHERE state = 'sale'. Als state geïndexeerd is, kan PostgreSQL die voorwaarde efficiënt via de index afhandelen zonder de volledige tabel te scannen.
Many2one‑velden illustreren dit goed: partner_id op een verkooporder bevat het id van de partner. Bij filteren op klant wordt er een WHERE partner_id = X uitgevoerd; met een index blijft die query snel, ook bij honderden duizenden orders.
Indexes en schrijfbewerking
Indexen hebben een prijs: bij elke insert, update of delete moet PostgreSQL ook de index(en) bijwerken. Hoe meer indexen op een tabel, hoe groter de schrijfoverhead. Vaak is de snelheidswinst bij lezen het waard, maar blindelings alles indexeren is niet verstandig.
De optie index='trigram'
Vanaf Odoo 16 kunt u in plaats van True ook 'trigram' opgeven voor index. Dat maakt een GIN‑trigramindex via de PostgreSQL‑extensie pg_trgm, ideaal voor snelle ILIKE/partiële zoekopdrachten op tekstvelden zoals product‑ of partnernamen.
name = fields.Char(string='Product Name', index='trigram')
Deze optie komt terug in standaardmodules waar velden vaak via gedeeltelijke tekstzoekopdrachten doorzocht worden.
Praktische bedrijfsvoorbeelden
Vijf concrete situaties waarin indexering verschil maakt
1. CRM: leads filteren per verantwoordelijke
In CRM filteren managers vaak op de verantwoordelijke gebruiker. Het user_id op crm.lead is standaard geïndexeerd, wat snelle filtering mogelijk maakt bij duizenden leads. Voor aangepaste Many2one‑velden geldt dezelfde redenering.
2. Verkoop: orders zoeken op status
Het state‑veld op sale.order is geïndexeerd, waardoor lijsten met bevestigde orders of filters voor ‘in afwachting van levering’ snel laden, ook bij hoge volumes. Selection‑velden die vaak als filter gebruikt worden, verdienen een index.
3. Magazijn: bewegingen per product traceren
Stock moves kunnen snel groeien in distributie of productie. Een index op product_id maakt het efficiënt om alle bewegingen voor een bepaald product op te vragen; zonder index worden traceer‑ en rapportagestructuren traag in drukke magazijnen.
4. Boekhouding: journaalposten filteren op partner
Accountants raadplegen vaak het grootboek per klant of leverancier. Een index op partner_id op account.move.line versnelt die zoekopdrachten en houdt rapporten zoals openstaande posten efficiënt, ook bij jaren aan boekingen.
5. Maatwerk: referentievelden voor traceerbaarheid
Bij maatwerk voegt u vaak referentievelden toe (projectcode, extern documentnummer). Worden die regelmatig gebruikt om te zoeken of filteren, dan is index=True een eenvoudige manier om prestaties op schaal te waarborgen.
Een geïndexeerd veld aanmaken of aanpassen
In Python (custom module‑ontwikkeling)
In een Pythonmodule voegt u index=True gewoon als keyword toe in de velddefinitie.
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'
)
Na toevoegen voert u een module‑upgrade uit (via odoo-bin -u your_module_name of de Apps‑interface). Odoo detecteert het nieuwe veld en maakt de index in de database aan.
U kunt ook een bestaand veld overriden om er een index aan toe te voegen, maar doe dat voorzichtig: het kan onbedoelde gevolgen hebben voor de oorspronkelijke veldlogica.
In Odoo Studio
Odoo Studio laat niet‑technische gebruikers velden aanmaken, maar biedt geen optie om indexering in te schakelen. Studio‑velden worden als handmatige velden in de database opgeslagen zonder standaard index=True.
Als een Studio‑veld geïndexeerd moet worden om performance te verbeteren, is de aanbevolen aanpak om de aanpassing om te zetten naar een Pythonmodule en daar index=True toe te voegen — een klus voor een ontwikkelaar.
Een index rechtstreeks in PostgreSQL aanmaken
Soms voegt een DBA in productie een index rechtstreeks toe met SQL zonder module‑upgrade, bijvoorbeeld bij optimalisatie van een bestaand systeem.
CREATE INDEX CONCURRENTLY idx_sale_order_partner_id
ON sale_order (partner_id);
Gebruik CONCURRENTLY om tabellen tijdens het bouwen van de index niet te blokkeren — essentieel in productie. Coördineer dergelijke acties met de moduledefinitie zodat code en database synchroon blijven; na‑volgende upgrades kunnen anders verrassingen geven.
Aanbevelingen en goede gewoonten
Indexeer velden die in search‑domains verschijnen
Velden die frequent in domains worden gebruikt — lijstfilters, automatiseringen, geplande jobs of als afhankelijkheden van berekende velden — zijn sterke kandidaten voor indexering. Denk aan Many2one’s, statusvelden en referentieveldnamen.
Volg Odoo’s eigen conventies
Een goede leidraad is Odoo’s eigen broncode: kijk welke velden in standaards als sale.order, account.move of stock.move geïndexeerd zijn. Deze keuzes weerspiegelen echte gebruikspatronen en praktijkervaring uit veel productieomgevingen.
Indexeer altijd Many2one‑velden op modellen met grote volumes
Bij modellen die sterk groeien (journaalposten, stock moves, verkooporderregels) is het aan te raden om Many2one‑velden die als filter dienen altijd te indexeren. De extra schrijfoverhead is meestal ruimschoots gerechtvaardigd door de lees‑ en zoekprestaties.
Overweeg trigramindexering voor tekstzoekvelden
Op Odoo 16+ is voor tekstvelden waar mensen gedeeltelijke termen typen (producten, partners, referenties) index='trigram' vaak de betere keuze dan een B‑tree, omdat trigram specifiek is geoptimaliseerd voor ILIKE‑matches.
Controleer dat indexen daadwerkelijk gebruikt worden
Na het aanmaken van een index controleert u met EXPLAIN ANALYZE of PostgreSQL die ook inzet. Als de planner nog steeds kiest voor een sequential scan, kan dat komen doordat de tabel te klein is of de query niet past bij het index‑type.
Documenteer uw beslissingen over indexering
Laat bij maatwerk kort achter waarom een veld geïndexeerd is. Dat voorkomt dat een toekomstige ontwikkelaar of consultant een schijnbaar onnodige index verwijdert en daardoor prestaties schaadt.
Veelvoorkomende valkuilen
Niet elk veld standaard indexeren
Een klassieke fout is index=True op elk veld zetten “voor de zekerheid”. Dat vergroot opslag en vertraagt schrijfbewerkingen onnodig. Op write‑intensieve tabellen zijn overbodige indexen vaak contraproductief.
Indexen op kleine tabellen zijn meestal overbodig
Bij tabellen van een paar honderd rijen kiest de planner vaak voor een sequential scan en levert een index weinig tot geen voordeel. Indexeren van kleine lookup‑tabellen of zelden gebruikte custom modellen voegt complexiteit toe zonder meetbare winst.
Vergeten de module te upgraden na het toevoegen van index=True
Het enkel aanpassen van de Python‑code is niet genoeg; u moet de module upgraden (-u module_name of via de backend) om de index te laten aanmaken. Dit vergeten veroorzaakt vaak verwarring tijdens development of wanneer staging/production niet synchroon lopen.
B-tree indexen versnellen geen ILIKE met leidende wildcard
Een gewone B‑tree helpt niet bij zoekpatronen zoals ILIKE '%zoekterm%' omdat PostgreSQL bij een leidende wildcard de index niet kan gebruiken. Voor snelle gedeeltelijke tekstzoekopdrachten gebruikt u trigram‑indexen of full‑text search.
Vergeet niet opgeslagen berekende velden
Berekende velden met store=True hebben wél een fysieke kolom en kunnen geïndexeerd worden. Ontwikkelaars vergeten dat soms en missen zo kansen om veelgebruikte afgeleide velden te versnellen.
Slotwoord
Kort samengevat: index=True is een klein attribuut in velddefinities, maar kan grote invloed hebben op databaseprestaties naarmate data groeit. Juist toegepast houdt het zoekacties en lijsten vlot; verkeerd toegepast creëert het extra overhead zonder voordeel.
De belangrijkste vuistregel: indexeer velden die regelmatig in domains gebruikt worden, vooral Many2one‑velden op grote modellen. Volg de keuzes in Odoo’s standaardmodules. Vermijd over‑indexeren van kleine tabellen en gebruik op Odoo 16+ index='trigram' voor tekstvelden die vaak met gedeeltelijke termen doorzocht worden.
Een doordachte indexeringsstrategie aan het begin van een ontwikkeltraject voorkomt veel pijn bij het oplossen van trage queries in productie later.
Werkt u aan een Odoo-implementatie?
Bij Dasolo begeleiden we bedrijven met implementatie, maatwerk en performance‑optimalisatie van Odoo. Of het nu gaat om nieuwe ontwikkeling, het versnellen van een bestaande installatie of het opzetten van een Odoo‑project, wij combineren praktijkervaring met technische diepgang.
Heeft u last van trage queries, complexe maatwerkproblemen of zoekt u advies over Odoo‑ontwikkeling? We helpen u graag verder. Neem contact op met het Dasolo‑team en vertel ons wat u aan het uitwerken bent.