[PERF] spreadsheet_account: optimize fetch_debit_credit SQL query

Issue:
Displaying the data on the dashboard accounting can take up to 1 minute

Analysis:
The spreadsheet_fetch_debit_credit function needs a domain in order to compute the formulas. The domain being set in `_build_spreadsheet_formula_domain` use a like search for account_account.code on account_move_line which is a big table. Thus it does not scale well. There is also a unnecessary complexity on adding an "OR expression" on each one of the account_id code searched for.

Solution:
It can be optimized by searching for the full exhaustive (like in SQL) codes in account.accoun since it has way less records and thus more scalable. And then use an exact condition (=) which is faster than a like search. Also adding more readable while adding the balance_domain and pnl domain only once in the whole query.

Benchmark:

| Before PR | After PR |
|:----------:|:---------:|
| 8s 51 ms | 42 ms code search + 42 ms full query |

Related ticket:
opw-3328144

Version affected:
16.0 and above

closes odoo/odoo#134889

X-original-commit: a707f8345cec8f404077b184f4b0339932c10892
Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
This commit is contained in:
Benjamin Hanquin (beha)
2023-09-08 16:48:01 +00:00
parent e0fdb6a0b4
commit 9b42ab531d
2 changed files with 8 additions and 7 deletions
+7 -6
View File
@@ -58,16 +58,17 @@ class AccountMove(models.Model):
("date", ">=", start),
("date", "<=", end),
]
# It is more optimized to (like) search for code directly in account.account than in account_move_line
code_domain = expression.OR(
[
expression.AND([
[("account_id.code", "=like", f"{code}%")],
expression.OR([balance_domain, pnl_domain]),
])
for code in codes
("code", "=like", f"{code}%"),
]
for code in codes
)
domain = expression.AND([code_domain, [("company_id", "=", company_id)]])
account_ids = self.env["account.account"].search(code_domain).ids
code_domain = [("account_id", "in", account_ids)]
period_domain = expression.OR([balance_domain, pnl_domain])
domain = expression.AND([code_domain, period_domain, [("company_id", "=", company_id)]])
if formula_params["include_unposted"]:
domain = expression.AND(
[domain, [("move_id.state", "!=", "cancel")]]
@@ -919,7 +919,7 @@ class SpreadsheetAccountingFunctionsTest(AccountTestInvoicingCommon):
"&",
"&",
"&",
("account_id.code", "=like", "sp1234566%"),
("account_id", "in", [self.account_revenue_c1.id]),
"|",
"&",
("account_id.include_initial_balance", "=", True),