The ORM in Odoo 19 allows for communication between the Python script and the PostgreSQL database. There are several operations, such as search(), create(), write(), and unlink(), among others, which are translated by Odoo into SQL queries. The automatic translation saves time and ensures clarity in code, but there may also be issues of efficiency and other problems not easily identified when using the ORM layer.
ORM Query Logs come in handy during such scenarios. They enable developers to track queries used in the course of an ORM operation, allowing them to locate slow-performing code, too many calls, and unnecessary queries run in a loop, among other issues. Developers who take the time to review ORM logs can enhance the functionality of modules, solve problems, and develop highly performant Odoo applications.
How ORM Query Logs Work in Odoo 19
The Odoo 19 ORM query logs reveal what the Python code is doing to the database. Although developers employ higher-level ORM commands, all actions result in SQL queries executed on the PostgreSQL database server. Query logs provide transparency of these queries, allowing developers to gauge the efficiency of their code interacting with the database.
For example, consider a simple ORM query:
partners = self.env['res.partner'].search([('customer_rank', '>', 0)])At first glance, this looks straightforward. However, Odoo converts it into an SQL query similar to:
SELECT id
FROM res_partner
WHERE customer_rank > 0;
When ORM query logging is enabled, this SQL statement becomes visible in the server logs. This is especially useful during development and debugging because it shows the exact database call made by the framework.
A typical log output may look like this:
2026-04-14 14:10:23,421 INFO db_name odoo.sql_db: query:
SELECT "res_partner"."id"
FROM "res_partner"
WHERE ("res_partner"."customer_rank" > 0)
This helps developers verify whether the ORM is generating the expected query.
One of the most important reasons ORM query logs matter is performance optimization. A piece of code may appear clean in Python, but can still generate multiple database hits.
Take this example:
orders = self.env['sale.order'].search([])
for order in orders:
print(order.partner_id.name)
This kind of code can lead to repeated queries if not handled carefully. If the related fields are not prefetched properly, each iteration may trigger additional SQL calls.
SELECT id FROM sale_order;
SELECT name FROM res_partner WHERE id = 3;
SELECT name FROM res_partner WHERE id = 5;
SELECT name FROM res_partner WHERE id = 8;
This pattern is commonly known as the N+1 query problem.
Instead of one optimized query, the system performs one query to fetch orders and multiple additional queries for related partner records. In a database with thousands of records, this can significantly slow down performance.
By reviewing ORM query logs, developers can quickly detect such issues.
A better approach would be:
orders = self.env['sale.order'].search([]).with_context(prefetch_fields=True)
for order in orders:
print(order.partner_id.name)
With optimized prefetching, the number of SQL queries is reduced, improving response time.
ORM query logs are also extremely useful while debugging custom modules.
Suppose a custom write() method is taking too long:
def write(self, vals):
result = super().write(vals)
self.env['audit.log'].create({
'name': self.name,
'status': 'updated'
})
return result
By checking the query logs, developers can identify whether the delay comes from the main write operation or from additional logging logic.
Example log:
UPDATE sale_order SET state='sale' WHERE id=12;
INSERT INTO audit_log (name, status) VALUES ('SO012', 'updated');
This level of visibility makes troubleshooting much easier.
Another major use case is detecting unnecessary queries inside loops.
For instance:
for product in products:
stock = self.env['stock.quant'].search([
('product_id', '=', product.id)
])
This may generate one query per product.
If there are 500 products, that means 500 database calls.
The logs immediately reveal this issue.
A more efficient solution would be batching:
stocks = self.env['stock.quant'].search([
('product_id', 'in', products.ids)
])
This converts multiple queries into a single optimized query.
In practice, when developing Odoo applications, this distinction plays a significant role in determining the performance and workload of your system.
This explains why ORM Query Logs are not only used for debugging but serve a useful function when writing code that performs well.
When implementing large Odoo applications, using ORM Query Logs will enable teams to ensure high performance while maintaining various modules like Sales, Purchase, Inventory, and Accounting.
In brief, ORM Query Logs assist Odoo developers in:
- Understanding automatically created SQL queries
- Discovering slow actions performed
- Finding duplicate queries
- Optimizing loops and relationships
- Improving the performance of their applications
All in all, ORM Query Logs play an indispensable role in the life of Odoo developers working with version 19.
In Odoo 19, ORM query logs are an effective tool that provides developers with an understanding of what is happening underneath neat and tidy-looking code. Although ORM allows for writing concise and readable code, sometimes its use may hide inefficiency of operations performed on the database side. With the help of proper query log analysis, developers get an opportunity to analyze their queries directly in the SQL code.
From a developer's point of view, such knowledge becomes especially useful when writing real applications. It enables developers to find inefficiencies earlier and write high-performance and scalable code by avoiding extra calls to the database. Regardless of whether developers are working on debugging slow features or enhancing their own custom modules, ORM query logs become an indispensable tool for doing this effectively and efficiently.
To read more about What Are the ORM Methods in Odoo 19, refer to our blog What Are the ORM Methods in Odoo 19.