Introducción
Si has pasado algún tiempo escribiendo o revisando definiciones de campos en Odoo, probablemente te hayas encontrado con algo como index=True en un campo. Parece pequeño, casi como un pensamiento secundario. Pero ese único atributo puede hacer una diferencia significativa en la rapidez con la que responde tu instancia de Odoo cuando los usuarios buscan, filtran o navegan por grandes conjuntos de datos.
Esta guía explica qué es un campo indexado en el contexto del modelo de datos de Odoo, cómo afecta a tu base de datos y cuándo tiene sentido usarlo en tu propio trabajo de desarrollo en Odoo. Ya sea que estés construyendo un módulo personalizado o revisando una implementación existente, entender este concepto te ayudará a tomar mejores decisiones.
¿Qué es un campo indexado en Odoo?
En el ORM de Odoo, un campo se declara indexado cuando su definición incluye index=True. Esto le indica a Odoo que le pida a PostgreSQL que cree un índice B-tree en la columna de base de datos correspondiente cuando se instale o actualice el módulo.
Aquí hay un ejemplo simple de una definición de campo de Odoo en Python:
class SaleOrder(models.Model):
_name = 'sale.order'
reference = fields.Char(string='Referencia', index=True)
state = fields.Selection([...], index=True)
partner_id = fields.Many2one('res.partner', index=True)
Desde la perspectiva de la interfaz de usuario, no hay nada visible sobre los campos indexados. Un usuario que completa un formulario o navega por una vista de lista no tiene forma de saber si un campo está indexado o no. La indexación es completamente una preocupación a nivel de base de datos.
Lo que afecta es la velocidad. Cuando un campo está indexado, PostgreSQL puede buscar registros coincidentes mucho más rápido, especialmente en tablas con miles o millones de filas. Sin un índice, la base de datos tiene que escanear cada fila en la tabla para encontrar las que coinciden con sus criterios de búsqueda. Con un índice, navega por una estructura ordenada y encuentra los resultados directamente.
Qué tipos de campo de Odoo soportan index=True
La mayoría de los tipos de campo escalar en el ORM de Odoo soportan el atributo index:
- Char y Text campos
- Integer y Float campos
- Date y Datetime campos
- Selection campos
- Many2one campos (muy comúnmente indexados)
- Boolean campos
Los campos relacionales como One2many y Many2many no tienen una columna directa para indexar de la misma manera, por lo que el atributo index no es relevante para ellos. Los campos computados que no están almacenados tampoco pueden ser indexados, ya que no tienen una columna en la base de datos.
Cómo funciona el campo
Cuando Odoo inicializa o actualiza un módulo, lee todas las definiciones de campo y sincroniza el esquema de la base de datos. Para cualquier campo con index=True, Odoo ejecuta una declaración SQL para crear un índice en esa columna en PostgreSQL.
Por defecto, PostgreSQL crea un índice B-tree, que es el tipo de índice estándar y funciona bien para comparaciones de igualdad (=), consultas de rango (>, <, BETWEEN) y ordenación. Esto cubre la gran mayoría de lo que Odoo hace al filtrar registros en vistas de lista o al computar búsquedas basadas en dominios.
Cómo Interactúa con el ORM de Odoo
El ORM de Odoo traduce los filtros de dominio de Python en consultas SQL. Cuando escribes un dominio como [('state', '=', 'sale')], el ORM genera algo como WHERE state = 'sale'. Si el campo state tiene un índice, PostgreSQL lo utiliza para resolver esa condición de manera eficiente sin escanear toda la tabla.
Los campos Many2one son un caso de uso muy común. En el modelo de datos de Odoo, un campo como partner_id en un pedido de venta almacena el ID entero del socio relacionado. Cuando abres la lista de pedidos filtrados por cliente, Odoo ejecuta una consulta con una condición WHERE partner_id = X. Con un índice en partner_id, esa búsqueda es rápida incluso con cientos de miles de pedidos en la base de datos.
Índices y Rendimiento de Escritura
Los índices no son gratuitos. Cada vez que se crea, actualiza o elimina un registro, PostgreSQL necesita actualizar todos los índices en esa tabla también. En tablas con muchos índices, las operaciones de escritura tardan un poco más. Para la mayoría de los casos de uso de Odoo, este compromiso vale la pena, pero es importante entender que indexar todo no siempre es la respuesta correcta.
La Opción index='trigram'
En Odoo 16 y versiones posteriores, el atributo index acepta no solo True sino también el valor de cadena 'trigram'. Esto crea un índice GIN trigram utilizando la extensión pg_trgm de PostgreSQL, que admite una coincidencia de patrones rápida con consultas ILIKE. Esto es particularmente útil para la búsqueda de texto en campos como nombres de productos o nombres de socios donde los usuarios a menudo escriben cadenas parciales en la barra de búsqueda.
name = fields.Char(string='Product Name', index='trigram')
Esta es una opción más avanzada utilizada en los propios módulos estándar de Odoo para campos que se buscan con frecuencia por texto parcial.
Casos de uso empresarial
Los campos indexados aparecen en muchos flujos de trabajo reales de Odoo. Aquí hay cinco ejemplos prácticos donde indexar un campo hace una diferencia notable.
1. CRM: Filtrando Leads por Vendedor
En CRM, los gerentes de ventas filtran regularmente el pipeline por vendedor. El campo user_id en crm.lead está indexado por defecto en Odoo, lo que hace que filtrar por vendedor sea rápido incluso con miles de leads. Si agregas un campo Many2one personalizado que apunte a un usuario o equipo, indexarlo sigue la misma lógica.
2. Ventas: Buscando Pedidos por Estado
El campo state en sale.order está indexado. Esto es lo que hace que cargar la lista de pedidos confirmados, o filtrar por pedidos en espera de entrega, sea rápido para las empresas que procesan grandes volúmenes. Los campos de selección que se utilizan frecuentemente como criterios de filtrado son buenos candidatos para la indexación.
3. Inventario: Rastreando Movimientos por Producto
Los movimientos de stock en Odoo pueden crecer a volúmenes muy grandes, especialmente en negocios de distribución o manufactura. El campo product_id en stock.move está indexado, lo que hace eficiente consultar todos los movimientos para un producto específico. Sin este índice, los informes de trazabilidad de productos se volverían dolorosamente lentos en almacenes ocupados.
4. Contabilidad: Filtrando Asientos por Socio
Los contadores abren frecuentemente el libro mayor para un cliente o proveedor específico. El partner_id en account.move.line está indexado para hacer que esas búsquedas sean eficientes. En empresas con años de historia contable, este índice es lo que evita que el informe de cuentas por cobrar envejecidas se agote.
5. Módulos Personalizados: Campos de Referencia para Trazabilidad
Al construir módulos personalizados, es común agregar campos de referencia que vinculan registros a través de modelos, por ejemplo, un código de proyecto personalizado o un número de documento externo. Si los usuarios buscarán o filtrarán regularmente por ese campo de referencia, agregar index=True es una forma sencilla de mantener esas búsquedas rápidas a medida que los datos crecen.
Crear o personalizar un campo indexado
En Python (Desarrollo de Módulos Personalizados)
Agregar index=True a una definición de campo en un módulo de Python es sencillo. Simplemente lo incluyes como un argumento de palabra clave al declarar el campo:
from odoo import models, fields
class ProjectTask(models.Model):
_inherit = 'project.task'
x_external_ref = fields.Char(
string='Referencia Externa',
index=True,
help='Número de referencia del sistema externo'
)
Después de agregar este campo a tu módulo, ejecuta odoo-bin -u your_module_name o actualiza el módulo a través del menú de Aplicaciones. Odoo detectará el nuevo campo y creará el índice correspondiente en la base de datos.
También puedes agregar un índice a un campo existente heredándolo y sobrescribiendo la definición, aunque este enfoque requiere cuidado para evitar efectos secundarios no deseados en el comportamiento del campo original.
En Odoo Studio
Odoo Studio permite a los usuarios no técnicos crear campos a través de la interfaz. Sin embargo, Studio actualmente no expone una opción para activar o desactivar el índice al crear campos. Los campos creados a través de Studio se almacenan en la base de datos como campos manuales y no tienen index=True configurado por defecto.
Si necesitas que un campo creado en Studio esté indexado por razones de rendimiento, el camino más limpio es convertir la personalización de Studio en un módulo de Python adecuado y agregar index=True en el código. Esto entra en la categoría de personalización técnica y generalmente es manejado por un desarrollador de Odoo en lugar de un usuario de Studio.
Agregar un Índice Directamente en PostgreSQL
En algunas situaciones, como al optimizar una base de datos de producción existente sin una actualización del módulo, un administrador de base de datos puede agregar un índice directamente usando SQL:
CREATE INDEX CONCURRENTLY idx_sale_order_partner_id
ON sale_order (partner_id);
Usar CONCURRENTLY evita bloquear la tabla durante la creación del índice, lo cual es importante en entornos de producción. Dicho esto, este enfoque debe coordinarse con la definición del módulo de Odoo para mantener el código de Python y la base de datos en sincronía. Si el módulo se actualiza más tarde, Odoo puede o no gestionar el índice dependiendo de lo que haya en la definición del campo.
Mejores prácticas
Índices de Campos que Aparecen en Dominios de Búsqueda
Si un campo se utiliza regularmente en filtros de dominio, ya sea en filtros de vista de lista, acciones automatizadas, trabajos programados o dependencias de campos computados, es un buen candidato para la indexación. Los ejemplos más comunes son los campos relacionales Many2one, los campos de estado y los campos de referencia o código.
Sigue las Propias Convenciones de Odoo
La mejor referencia para saber cuándo usar index=True es el propio código fuente de Odoo. Mira las definiciones de campos estándar en sale.order, account.move o stock.move para ver qué campos eligieron indexar los propios desarrolladores de Odoo. Esas elecciones se basan en patrones de uso reales y datos de rendimiento de miles de bases de datos en producción.
Siempre Indexa Campos Many2one en Modelos de Alto Volumen
Para modelos que acumulan un gran número de registros con el tiempo (asientos contables, movimientos de stock, líneas de pedidos de venta), siempre indexa los campos Many2one que se utilizan para filtrar. El costo de un índice adicional en una tabla con muchas escrituras casi siempre vale la pena por la mejora en el rendimiento de lectura.
Considera la Indexación Trigram para Campos de Búsqueda de Texto
En Odoo 16 y versiones posteriores, si los usuarios buscan frecuentemente registros escribiendo cadenas parciales en un campo Char como el nombre de un producto, el nombre de un socio o una referencia de documento, considera usar index='trigram' en lugar del índice B-tree por defecto. Los índices trigram están diseñados específicamente para la coincidencia de patrones ILIKE.
Verifica que los Índices Estén Siendo Usados Realmente
Después de agregar un índice, puedes verificar que PostgreSQL lo esté utilizando ejecutando un EXPLAIN ANALYZE en la consulta. Si el planificador de consultas sigue eligiendo un escaneo secuencial, la tabla puede ser demasiado pequeña para que el índice sea beneficioso, o las condiciones de la consulta pueden no ser compatibles con el tipo de índice.
Documenta tus Decisiones de Indexación
Al construir módulos personalizados, deja un breve comentario explicando por qué se indexa un campo. Esto ayuda a futuros desarrolladores y consultores a entender la intención y evitar eliminar el índice por accidente durante una refactorización.
Errores comunes
Indexar Cada Campo por Defecto
Un error común al aprender sobre indexación es agregar index=True a cada campo solo para estar seguro. Esto es contraproducente. Cada índice ocupa espacio de almacenamiento y añade sobrecarga a cada operación de escritura. En tablas que reciben un alto volumen de inserciones o actualizaciones, los índices innecesarios pueden ralentizar notablemente el sistema.
Indexación de Campos en Tablas Pequeñas
En tablas con unos pocos cientos de filas, el planificador de consultas de PostgreSQL a menudo decide que un escaneo secuencial es más rápido que usar un índice. Los índices comienzan a proporcionar un beneficio real a medida que las tablas crecen a miles de registros y más. Indexar pequeñas tablas de búsqueda o modelos personalizados raramente poblados añade complejidad sin ningún beneficio práctico.
Olvidar Actualizar el Módulo Después de Agregar index=True
Simplemente agregar index=True a una definición de campo en Python no crea automáticamente el índice en la base de datos. Necesitas actualizar el módulo usando -u module_name o a través del backend de Odoo. Olvidar este paso es una fuente frecuente de confusión durante el desarrollo y puede llevar a problemas de rendimiento en entornos de staging o producción donde se omitió la actualización.
Esperar que los Índices Aceleren las Búsquedas ILIKE en Campos Char
Un índice B-tree regular con index=True no ayuda con las consultas ILIKE '%keyword%' donde el comodín está al inicio del patrón. PostgreSQL no puede usar un índice B-tree para evaluar un comodín líder. Si necesitas una búsqueda de texto parcial rápida, usa index='trigram' en Odoo 16+ o explora opciones de búsqueda de texto completo.
No Considerar Campos Computados Almacenados
Los campos computados almacenados (aquellos con store=True) sí tienen una columna en la base de datos y pueden ser indexados. Los desarrolladores a veces pasan por alto esto y pierden la oportunidad de mejorar el rendimiento en campos que agregan o derivan valores utilizados intensamente en filtros. Si un campo computado almacenado aparece en filtros de dominio a través de informes o vistas, vale la pena considerar su indexación.
Conclusión
El atributo index=True es un pequeño detalle en la definición de campo de Odoo, pero tiene un impacto real en el rendimiento de la base de datos a medida que tus datos crecen. Usado correctamente, mantiene las búsquedas rápidas, las vistas de lista receptivas y los informes rápidos de generar. Usado descuidadamente, añade sobrecarga sin ningún beneficio.
La conclusión clave es simple: indexa los campos que se utilizan regularmente en filtros de dominio, especialmente los campos Many2one en modelos de alto volumen. Sigue los patrones establecidos por los propios módulos estándar de Odoo. Evita la sobreindexación de tablas pequeñas o campos que nunca se filtran. Y si estás en Odoo 16 o posterior, considera index='trigram' para campos de búsqueda de texto donde los usuarios escriben cadenas parciales.
Acertar con la estrategia de indexación desde el inicio de un proyecto de desarrollo personalizado es mucho más fácil que diagnosticar consultas lentas en producción más tarde.
¿Trabajando en una implementación de Odoo?
En Dasolo, ayudamos a las empresas a implementar, personalizar y optimizar Odoo. Ya sea que esté construyendo módulos personalizados, mejorando el rendimiento de una instancia existente o planificando un nuevo proyecto de Odoo desde cero, aportamos experiencia técnica práctica a cada compromiso.
Si está lidiando con consultas lentas, personalizaciones complejas o necesita orientación sobre las mejores prácticas de desarrollo de Odoo, estaremos encantados de ayudarle. Póngase en contacto con el equipo de Dasolo y háganos saber en qué está trabajando.