Introdução
Se já trabalhou com definições de campos no Odoo, provavelmente reparou naquela pequena flag index=True. Parece um pormenor, mas pode transformar completamente a velocidade de consultas quando os utilizadores pesquisam ou filtram grandes volumes de dados.
Este artigo explica de forma prática o que significa indexar um campo no modelo de dados do Odoo, como essa escolha se traduz no banco de dados PostgreSQL e quando vale a pena usá-la — seja a criar módulos personalizados ou a rever uma implementação existente.
O que significa um campo indexado no Odoo
No ORM do Odoo, um campo fica marcado como indexado quando a sua definição inclui index=True. Com isso, o Odoo instrui o PostgreSQL a criar um índice na coluna correspondente sempre que o módulo é instalado ou atualizado.
Para entender melhor, pense nisso como uma instrução que garante ao banco de dados uma estrutura adicional para localizar valores mais depressa do que lendo toda a tabela.
Por exemplo, num módulo de vendas pode haver campos definidos assim:
Para o utilizador final não existe qualquer indicação visível de que um campo está indexado — o comportamento altera-se apenas ao nível do banco de dados. Quem preenche formulários ou navega em vistas de lista não vê nenhuma etiqueta a dizer “indexado”.
O impacto real é a performance. Num campo indexado, o PostgreSQL procura valores através de uma estrutura ordenada, evitando a leitura linha a linha. Em tabelas com milhares ou milhões de registos, essa diferença traduz-se em pesquisas e filtros muito mais rápidos.
Que tipos de campo suportam indexação no Odoo
Na prática, a maioria dos campos escalares do ORM aceita o atributo index.
- Campos de texto curtos, como Char, e campos de texto longo, como Text, podem ser indexados (com ressalvas para pesquisas por padrões).
- Campos numéricos — Integer e Float — também aceitam índice, úteis para filtros por código ou quantidades.
- Campos de data e hora (Date, Datetime) podem receber índice para acelerar pesquisas por períodos.
- Campos Selection são indexáveis e isso faz sentido quando os estados são usados frequentemente como critério de filtro.
- Many2one é um caso típico: relacionamentos que guardam um ID estrangeiro são frequentemente indexados para acelerar junções e buscas por referência.
- Mesmo Boolean pode ter índice, embora o benefício dependa da distribuição dos valores.
Campos relacionais que não correspondem a uma coluna direta no registo (One2many, Many2many) não usam o atributo index do mesmo modo. E campos calculados que não são armazenados não têm coluna para indexar.
Como funciona na prática
Quando o Odoo instala ou atualiza um módulo, ele compara as definições de campos com o esquema do banco e aplica as alterações necessárias. Para qualquer campo com index=True, o sistema envia ao PostgreSQL o comando para criar o índice nessa coluna.
Por defeito cria-se um índice B-tree, o tipo mais comum e adequado para igualdade, intervalos (>, <, BETWEEN) e ordenação — exatamente os casos mais frequentes nas pesquisas e filtros do Odoo.
Interação com o ORM do Odoo
O ORM converte domínios Python em SQL. Um domínio como [('state', '=', 'sale')] torna-se um WHERE no SQL. Se a coluna tiver índice, o PostgreSQL pode usar essa estrutura para responder à condição muito mais depressa do que fazendo um scan completo da tabela.
No caso de campos Many2one, o ganho é evidente: o campo armazena o ID do registo relacionado e consultas do tipo WHERE partner_id = X são comumíssimas — um índice torna essas consultas rápidas mesmo em bases com centenas de milhares de registos.
Índices e performance de escrita
Índices têm custo. Sempre que cria, atualiza ou elimina um registo, o PostgreSQL actualiza os índices correspondentes. Muitas colunas indexadas numa tabela aumentam a latência das operações de escrita. Na maioria dos cenários do Odoo esse custo é aceitável, mas não convém indexar tudo indiscriminadamente.
A opção index='trigram'
A partir do Odoo 16, o atributo index pode receber o valor 'trigram'. Isso cria um índice GIN baseado em trigramas (extensão pg_trgm) — ideal para pesquisas por padrão com ILIKE e para corresponder partes de palavras.
Exemplo de uso prático: name = fields.Char(string='Nome do Produto', index='trigram')
Esta opção é usada em campos de texto que os utilizadores pesquisam por pedaços de string, como nomes de produto ou de parceiro, melhorando muito a experiência de pesquisa parcial.
Casos de uso empresariais
Cinco situações reais onde a indexação faz diferença
1. CRM: filtrar leads por responsável
No CRM, os gestores filtram frequentemente o funil por utilizador. Campos como user_id em crm.lead vêm indexados por defeito porque sem esse índice a pesquisa por responsável seria lenta com milhares de leads.
2. Vendas: filtrar encomendas por estado
Campos de estado em sale.order (ex.: state) são indexados para permitir filtrar rapidamente encomendas confirmadas, pendentes ou em entrega — crucial em empresas com grande volume de pedidos.
3. Inventário: movimentos por produto
Em armazéns muito ativos, os registos de stock move crescem muito. Ter product_id indexado em stock.move permite gerar relatórios de rastreabilidade e consultar movimentos por produto sem lentidões.
4. Contabilidade: lançar diários por parceiro
Contabilistas frequentemente consultam lançamentos por cliente ou fornecedor. O índice em partner_id em linhas de movimento contabilístico mantém consultas e relatórios históricos com bom desempenho, mesmo em bases antigas.
5. Módulos personalizados: campos de referência para rastreio
Ao criar módulos personalizados, se acrescenta um campo de referência que os utilizadores vão filtrar com frequência (ex.: código externo, número de documento), vale a pena indexá-lo para manter a pesquisa ágil com o crescimento dos dados.
Criar ou personalizar um campo indexado
Como adicionar um índice em código Python
Na definição do campo em Python basta incluir index=True como argumento ao declarar o campo.
Exemplo numa herança de projeto:
Depois de alterar o código é necessário atualizar o módulo (por exemplo com odoo-bin -u nome_modulo) ou fazer a atualização pela interface de Apps para que o Odoo aplique o novo índice no banco de dados.
Também é possível criar um índice alterando a definição de um campo herdado, mas isso exige cuidado para não introduzir efeitos colaterais no comportamento original do campo.
E quanto ao Odoo Studio?
Odoo Studio facilita a criação de campos pela interface, mas não expõe hoje a opção para activar a indexação. Os campos criados por Studio não vêm com index=True por defeito.
Se uma coluna criada em Studio precisa de indexação por motivos de desempenho, a melhor prática é transformar essa customização num módulo Python e adicionar o índice em código — tarefa normalmente realizada por um desenvolvedor Odoo.
Criar um índice diretamente no PostgreSQL
Em ambientes em produção, um administrador pode optar por criar um índice diretamente no banco quando não é conveniente atualizar o módulo:
Exemplo SQL:
Usar CONCURRENTLY permite criar o índice sem bloquear a tabela, o que é crítico em produção. Contudo, convém alinhar essa alteração com a definição do módulo para evitar desfasamentos entre o código e o esquema do banco.
Boas práticas
Quais campos devem ser indexados
Campos usados regularmente em domínios — filtros em vistas de lista, ações automáticas, cron jobs ou dependências de campos calculados armazenados — são candidatos claros à indexação. Exemplos típicos: Many2one, campos de estado e campos de referência ou código.
Seguir as convenções do Odoo
Um bom indicador do que indexar é olhar para os módulos padrão do Odoo. Os campos que a própria equipa do Odoo escolheu indexar reflectem padrões de uso reais e são um excelente guia de boas práticas.
Indexar Many2one em modelos de grande volume
Em tabelas que acumulam muitos registos (lançamentos contabilísticos, movimentos de stock, linhas de encomenda), é quase sempre sensato indexar os Many2one que servem de critério de pesquisa — o ganho de leitura compensa o pequeno custo adicional nas escritas.
Ponderar trigram para pesquisas de texto
Se os utilizadores procuram por fragmentos de texto em campos Char (nomes, referências), em Odoo 16+ considere index='trigram' em vez do B-tree para melhorar as pesquisas com ILIKE.
Confirmar que o índice está a ser usado
Depois de criar um índice, valide o seu impacto com um EXPLAIN ANALYZE. Se o plano continuar a usar um sequential scan, pode ser porque a tabela ainda é pequena ou porque a consulta não aproveita o tipo de índice criado.
Registar porque indexou um campo
Deixe um comentário no código a justificar a indexação. Isso ajuda quem vier a manter o módulo a entender a razão da escolha e evita que um índice útil seja removido inadvertidamente durante refatores.
Erros comuns a evitar
Evite indexar tudo por defeito
Um erro comum é pôr index=True em todos os campos “por segurança”. Cada índice ocupa espaço e penaliza escritas; em tabelas com muitas inserções/atualizações, índices desnecessários podem degradar a performance global.
Não indexar tabelas pequenas
Em tabelas com poucas centenas de registos, o planner do PostgreSQL normalmente prefere um scan sequencial. Índices só começam a compensar quando a tabela cresce para milhares de registos. Indexar tabelas pequenas ou modelos esporádicos traz pouca vantagem prática.
Esquecer de atualizar o módulo após adicionar index=True
Adicionar a flag no ficheiro Python não cria imediatamente o índice. É preciso atualizar o módulo com -u nome_modulo ou pela interface. Esquecer essa etapa é uma causa frequente de confusão durante o desenvolvimento.
Não esperar que B-tree acelere pesquisas com ILIKE e prefixos curinga
Um índice B-tree não resolve consultas do tipo ILIKE '%palavra%' (curinga inicial). Para pesquisas parciais com wildcard em qualquer posição, use index='trigram' ou outras soluções de pesquisa textual.
Ignorar campos calculados armazenados
Campos computados com store=True geram colunas físicas e podem ser indexados. Muitas vezes os desenvolvedores esquecem essa opção e perdem a oportunidade de optimizar filtros que dependem desses valores.
Conclusão
O atributo index=True é um detalhe pequeno no código, mas com impacto real na performance à medida que a base cresce. Bem usado, mantém as pesquisas e relatórios rápidos; mal usado, só adiciona sobrecarga sem retorno.
A ideia principal é simples: indexe campos que aparecem constantemente em domínios, sobretudo Many2one em modelos de alto volume. Inspire-se nas escolhas dos módulos padrão do Odoo. Evite indexar tabelas pequenas ou campos raramente filtrados. E em Odoo 16+ considere index='trigram' para campos de pesquisa textual parcial.
Definir a estratégia de indexação no início do projeto facilita muito a vida — é preferível prevenir consultas lentas do que tentar corrigir performance em produção.
A implementar um projeto Odoo?
Na Dasolo ajudamos empresas a implementar, personalizar e optimizar Odoo. Seja a desenvolver módulos, a melhorar o desempenho de uma instância existente ou a planear um projecto do zero, trazemos experiência técnica prática a cada intervenção.
Se tem consultas lentas, personalizações complexas ou precisa de aconselhamento sobre boas práticas de desenvolvimento em Odoo, podemos ajudar. Contacte a equipa Dasolo e conte-nos o que está a implementar.