From d982c4f319ee3d6af7e4820ab37e5d93a80a6544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet=20=28ryv=29?= Date: Thu, 1 Sep 2022 12:53:01 +0000 Subject: [PATCH] [IMP] core: save one query when reading one2many on a single record MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For reading one2many fields, we make 2 queries (in batch): - One to search "id" the comodel - One to read 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 --- odoo/fields.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/odoo/fields.py b/odoo/fields.py index defae754926..2f49423ff8d 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -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