Enable Dark Mode!
how-to-improve-data-model-efficiency-with-computed-fields-in-odoo-19.jpg
By: Muhammed Fahis V P

How to Improve Data Model Efficiency with Computed Fields in Odoo 19

Technical Odoo 19 Fields and widgets

In large-scale ERP implementations, the performance tuning does not confine server configuration or worker’s settings. For Odoo 19, a major chunk of performance tuning is in how developers design their data models. Among all ORM features, computed fields can do a lot, but also cause one of the primary reasons for having slow views and loading the database more heavily if not implemented wisely.

Computed fields provide an opportunity for developers to dynamically compute values from other fields. This keeps the business logic clean and eliminates data duplication. But to avoid performance bottlenecks, it's imperative to know the internal operations performed by Odoo in relation to these computed fields.

How Computed Fields Work in Odoo 19

A computed field is defined through the compute parameter, where a method dynamically calculates the value.

total_amount = fields.Float(
    string="Total Amount",
    compute="_compute_total_amount"
)
@api.depends('line_ids.price_subtotal')
def _compute_total_amount(self):
    for record in self:
        record.total_amount = sum(record.line_ids.mapped('price_subtotal'))

By default, computed fields do not have to be stored in the database. By default, computed fields are not stored in the database; whether in form view, tree view, export, or a report, Odoo executes the compute method again.

This behavior is well-suited for small datasets. However, in production databases with thousands of records, repeated recalculation wastes a lot of resources and can severely degrade performance.

The Importance of store=True

When store=True is added, Odoo creates a database column and stores the computed value. Odoo, therefore, recalculates the field only when one of its dependencies is changed.

profit_margin = fields.Float(
    compute="_compute_profit_margin",
    store=True
)

This drastically improves read performance, notably in:

  • Tree view of many records
  • Search filters
  • Group-By
  • Report

However, storing a field increases the write overhead because Odoo must recompute it whenever dependent fields are modified. When deciding regarding storing a computed field, it is imperative to consider a comparison between how often the computed field is read and the rate at which its dependencies are altered.

Writing Precise Dependencies

@api.depends decorator is responsible for controlling when Odoo does the recomputation. Such broad dependencies lead to a number of unnecessary recalculations.

For instance:

@api.depends('line_ids.price_subtotal')

This will trigger the recompute for any change in the one2many field.

A more accurate approach is:

@api.depends('line_ids.price_subtotal')

This ensures recomputation is done only when the corresponding field is updated. The precise declaration of dependencies can help to ensure that in high-volume transactional models, not much is done redundantly.

Avoiding Queries Inside Loops

Second, a common mistake found in compute methods is querying databases inside a loop.

def _compute_invoice_count(self):
    for record in self:
        invoices = self.env['account.move'].search([
            ('partner_id', '=', record.id)
        ])
        record.invoice_count = len(invoices)

If the recordset has 500 records, that means 500 database queries. In real environments, this pattern affects performance severely.

Instead, there should be batch processing:

def _compute_invoice_count(self):
    grouped_data = self.env['account.move'].read_group(
        [('partner_id', 'in', self.ids)],
        ['partner_id'],
        ['partner_id']
    )
    result = {
        data['partner_id'][0]: data['partner_id_count']
        for data in grouped_data
    }
    for record in self:
        record.invoice_count = result.get(record.id, 0)

The result is a single grouped query instead of multiple queries and hence, the computations become scalable.

Using Related Fields Instead of Computed Fields

In some cases, developers use computed fields to get values from related models. This introduces extra logic.

Rather than use a compute method to assign partner_id.name, it is better and cleaner to use related field:

partner_name = fields.Char(
    related="partner_id.name",
    store=True
)

Related fields are optimized internally and reduce complexities in coding.

Managing Dependency Chains

When stored computed fields rely on other stored computed fields, Odoo produces recomputation chains. Thus, Odoo builds recomputation chains for stored computed fields depending on other stored computed fields.

To avoid excessive cascading recomputation:

  • Keep dependency chains short
  • Avoid unnecessary computed-to-computed dependencies
  • Combine related logic as much as possible

This is especially critical in custom modules created on top of sales, accounting, or inventory models.

Indexing Stored Computed Fields

If the stored computed field is constantly used in domain filters, enabling indexing has benefits on search performance.

is_profitable = fields.Boolean(
    compute="_compute_profitability",
    store=True,
    index=True
)

Indexing is beneficial in large models such as sales orders or invoices with filtering.

Computed fields are one of the core and required notions of the Odoo 19 ORM in relation to implementing dynamic business logic. Their benefits must, however, be preceded by appropriate performance considerations.

Optimizing computed fields involves an understanding of Odoo’s recalculation approach, dependencies, and storage in the database. Defining dependencies, using store=True wisely, avoiding queries during iterations, and using related fields wherever possible ensure optimum efficiency of custom modules as the data consumed increases. A well-designed data model guarantees long-term scalability and maintainability in a production environment, in addition to improving system speed.

To read more about How to Add a Search Filter for Computed Fields in Odoo 18,refer to our blog How to Add a Search Filter for Computed Fields in Odoo 18.


Frequently Asked Questions

Does adding store=True always improve performance?

Not always. It is true that the read performance is improved but the overhead of write is also hiked. If a field is displayed often and its dependencies get changed rarely, storing the extra field value is beneficial. Otherwise, it is unnecessary.

Why does tree view get slow after adding a computed field?

If the field is not stored, Odoo will recalculate the field for every record displayed in the tree view. This causes delays when there are many records and a tree view is displayed.

Is it safe to call search() inside compute methods?

It is allowed officially, but using search() in loops is inefficient. When looking up multiple records, batch operations such as read_group are always preferred.

Can computed fields increase the size of a database?

Yes. They create additional columns in the database when they are stored. However, the cost of storage is very much minimal when compared to the benefit of performance.

How do I decide to store a computed field?

Ask whether the field applies in search filters, reports, group-by fields, or a frequently accessed list page. If yes, storing is recommended for most cases.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message