Skip to content

Commit

Permalink
[FIX] prefetch issues on computed/related fields
Browse files Browse the repository at this point in the history
When deciding to prefetch records (getting records from the cache with
no value for the field being fetched), if the field was computed
determine_value would just get all records, not limited by the normal
prefetch limit, for large recordsets this would generate gigantic
prefetch lists for records we may not need at all.

Fix by applying the PREFETCH_MAX limit to records from the cache as is
done in _prefetch_field.

Complementarily, when traversing related fields the prefetch
environment would be lost and every record would get an empty prefetch
environment, so the values would ultimately be read one by one.

Example: select (search) 1000 product.product records, access a
related field (e.g. categ_id) in a loop, on the first iteration the
system would first read 1000 templates, then it would read each
categ_id individually, resulting in >1000 SQL queries rather than the
~2 we would expect.

Fixes odoo#18511
  • Loading branch information
xmo-odoo authored and sle-odoo committed Aug 3, 2017
1 parent 7b27995 commit 5007e38
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions odoo/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ def traverse_related(self, record):
""" Traverse the fields of the related field `self` except for the last
one, and return it as a pair `(last_record, last_field)`. """
for name in self.related[:-1]:
record = record[name][:1]
record = record[name][:1].with_prefetch(record._prefetch)
return record, self.related_field

def _compute_related(self, records):
Expand Down Expand Up @@ -981,6 +981,8 @@ def determine_value(self, record):
self.compute_value(record)
else:
recs = record._in_cache_without(self)
if len(recs) > PREFETCH_MAX:
recs = recs[:PREFETCH_MAX] | record
self.compute_value(recs)

else:
Expand Down Expand Up @@ -2445,4 +2447,4 @@ def __set__(self, record, value):
# imported here to avoid dependency cycle issues
from odoo import SUPERUSER_ID
from .exceptions import AccessError, MissingError, UserError
from .models import check_pg_name, BaseModel, IdType
from .models import check_pg_name, BaseModel, IdType, PREFETCH_MAX

1 comment on commit 5007e38

@xmo-odoo
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sle-odoo cf odoo#18644 (comment) it looks like the second chunk loses the prefetch info, and there could be an additional one for relational fields.

Please sign in to comment.