From 60dbf05750532519c4cb73cd764ca9df37d7b229 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Mon, 4 Sep 2017 14:52:03 +0200 Subject: [PATCH] [FIX] stock: performance issue Commit 6a366b216b3d1 introduces a subquery when fetching translations in order to avoid fetching duplicates. On large a `ir.translation` table (~500000 records), this can cause a major performance degradation when the user is not using the English language. A typical example is a `read_group` call such as: ``` self.env['stock.quant'].with_context(lang='fr_BE').read_group([ ('location_id', 'child_of', self.env.ref('stock.stock_location_stock').id)], ['product_id', 'qty'], ['product_id'], limit=80) ``` When no `orderby` parameter is used, the `groupby` fields are implicitly used for ordering. While this makes sense for direct calls from the web client, this implicit order might be problematic for programmatic calls (such as computed fields). Indeed, in case of grouping by product, the subquery mentioned earlier is used to sort by product name. This is costly, and in most of the cases useless. The workaround is to explicitely order by `id`, to avoid the use of the subquery. For the upcoming version, a cleaner fix should be made in order to prevent duplicated translations, and get rid of the subquery. opw-767532 --- addons/stock/models/product.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index 015e6d98896..d581fde2855 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -143,15 +143,15 @@ class Product(models.Model): Quant = self.env['stock.quant'] domain_move_in_todo = [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_move_in domain_move_out_todo = [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_move_out - moves_in_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_in_todo, ['product_id', 'product_qty'], ['product_id'])) - moves_out_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_out_todo, ['product_id', 'product_qty'], ['product_id'])) - quants_res = dict((item['product_id'][0], item['qty']) for item in Quant.read_group(domain_quant, ['product_id', 'qty'], ['product_id'])) + moves_in_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_in_todo, ['product_id', 'product_qty'], ['product_id'], orderby='id')) + moves_out_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_out_todo, ['product_id', 'product_qty'], ['product_id'], orderby='id')) + quants_res = dict((item['product_id'][0], item['qty']) for item in Quant.read_group(domain_quant, ['product_id', 'qty'], ['product_id'], orderby='id')) if dates_in_the_past: # Calculate the moves that were done before now to calculate back in time (as most questions will be recent ones) domain_move_in_done = [('state', '=', 'done'), ('date', '>', to_date)] + domain_move_in_done domain_move_out_done = [('state', '=', 'done'), ('date', '>', to_date)] + domain_move_out_done - moves_in_res_past = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_in_done, ['product_id', 'product_qty'], ['product_id'])) - moves_out_res_past = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_out_done, ['product_id', 'product_qty'], ['product_id'])) + moves_in_res_past = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_in_done, ['product_id', 'product_qty'], ['product_id'], orderby='id')) + moves_out_res_past = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_out_done, ['product_id', 'product_qty'], ['product_id'], orderby='id')) res = dict() for product in self.with_context(prefetch_fields=False): @@ -288,7 +288,7 @@ class Product(models.Model): domain_quant.append(('owner_id', '=', owner_id)) if package_id: domain_quant.append(('package_id', '=', package_id)) - quants_groupby = self.env['stock.quant'].read_group(domain_quant, ['product_id', 'qty'], ['product_id']) + quants_groupby = self.env['stock.quant'].read_group(domain_quant, ['product_id', 'qty'], ['product_id'], orderby='id') for quant in quants_groupby: if OPERATORS[operator](quant['qty'], value): product_ids.add(quant['product_id'][0])