[IMP] core: save one query when reading one2many on a single record

For reading one2many fields, we make 2 queries (in batch):
- One to search "id" the comodel
- One to read <inverse_field> in the comodel to group lines by record
(sometimes, this one is bypass because the cache already contains the information).

In many cases (> 80% of cases in our tests) we read a one2many field on
a single record.  In that case, we can avoid the second query completely
(grouping all lines on a single record is trivial).

This reduces SQL queries by about 0.8% on all-install runbot builds.

closes odoo/odoo#99415

Signed-off-by: Rémy Voet <ryv@odoo.com>
This commit is contained in:
Rémy Voet (ryv)
2022-09-02 23:16:13 +02:00
committed by Raphael Collet
parent dfa34aa3fe
commit d982c4f319
+8 -1
View File
@@ -4165,11 +4165,18 @@ class One2many(_RelationalMulti):
comodel = records.env[self.comodel_name].with_context(**context)
inverse = self.inverse_name
inverse_field = comodel._fields[inverse]
get_id = (lambda rec: rec.id) if inverse_field.type == 'many2one' else int
domain = self.get_domain_list(records) + [(inverse, 'in', records.ids)]
lines = comodel.search(domain)
if len(records) == 1:
# optimization: all lines have the same value for 'inverse_field',
# so we don't need to fetch it from database
records.env.cache.insert_missing(records, self, [lines._ids])
records.env.cache.insert_missing(lines, inverse_field, itertools.repeat(records.id))
return
# group lines by inverse field (without prefetching other fields)
get_id = (lambda rec: rec.id) if inverse_field.type == 'many2one' else int
group = defaultdict(list)
for line in lines.with_context(prefetch_fields=False):
# line[inverse] may be a record or an integer