e2ffff1e427be1e98a64de1d2c8a837447d47538
The domain used in `get_filters`, used in `get_views` is
```python
[('action_id', 'in', [action_id, False]), ('model_id', '=', model), ('user_id', 'in', [self._uid, False])]
```
Therefore filtering the filters on `action_id`, `model_id` and
`user_id`.
An index on `(action_id, model_id, user_id)` would therefore be welcome
in order to search quicker on filters.
The unique constraint `name_model_uid_unique` almost does it,
but it puts the name in first, and therefore the index is not used
when searching on the above domain.
By moving `name` to the end of the unique constraint,
the index created for this unique constraint becomes
usable for the above domain,
and it makes the SQL statement to search on filters way quicker.
Before:
```sql
EXPLAIN ANALYZE SELECT "ir_filters".id FROM "ir_filters" LEFT JOIN "ir_translation" AS "ir_filters__name" ON ("ir_filters"."id" = "ir_filters__name"."res_id" AND "ir_filters__name"."type" = 'model' AND "ir_filters__name"."name" = 'ir.filters,name' AND "ir_filters__name"."lang" = 'en_US' AND "ir_filters__name"."value" != '') WHERE (((("ir_filters"."active" = true) AND (("ir_filters"."action_id" in (225)) OR "ir_filters"."action_id" IS NULL)) AND ("ir_filters"."model_id" = 'account.move')) AND (("ir_filters"."user_id" in (2)) OR "ir_filters"."user_id" IS NULL)) AND TRUE ORDER BY "ir_filters"."model_id" ,COALESCE("ir_filters__name"."value", "ir_filters"."name") ,"ir_filters"."id" DESC;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=3500.58..3500.59 rows=1 width=56) (actual time=12.940..12.942 rows=0 loops=1)
Sort Key: (COALESCE(ir_filters__name.value, (ir_filters.name)::text)), ir_filters.id DESC
Sort Method: quicksort Memory: 25kB
-> Nested Loop Left Join (cost=0.00..3500.57 rows=1 width=56) (actual time=12.933..12.934 rows=0 loops=1)
Join Filter: (ir_filters.id = ir_filters__name.res_id)
-> Seq Scan on ir_filters (cost=0.00..3499.02 rows=1 width=36) (actual time=12.932..12.932 rows=0 loops=1)
Filter: (active AND ((action_id = 225) OR (action_id IS NULL)) AND ((user_id = 2) OR (user_id IS NULL)) AND ((model_id)::text = 'account.move'::text))
Rows Removed by Filter: 100001
-> Seq Scan on ir_translation ir_filters__name (cost=0.00..1.54 rows=1 width=36) (never executed)
Filter: ((value <> ''::text) AND ((type)::text = 'model'::text) AND ((name)::text = 'ir.filters,name'::text) AND ((lang)::text = 'en_US'::text))
Planning Time: 0.311 ms
Execution Time: 12.972 ms
```
After:
```sql
EXPLAIN ANALYZE SELECT "ir_filters".id FROM "ir_filters" LEFT JOIN "ir_translation" AS "ir_filters__name" ON ("ir_filters"."id" = "ir_filters__name"."res_id" AND "ir_filters__name"."type" = 'model' AND "ir_filters__name"."name" = 'ir.filters,name' AND "ir_filters__name"."lang" = 'en_US' AND "ir_filters__name"."value" != '') WHERE (((("ir_filters"."active" = true) AND (("ir_filters"."action_id" in (225)) OR "ir_filters"."action_id" IS NULL)) AND ("ir_filters"."model_id" = 'account.move')) AND (("ir_filters"."user_id" in (2)) OR "ir_filters"."user_id" IS NULL)) AND TRUE ORDER BY "ir_filters"."model_id" ,COALESCE("ir_filters__name"."value", "ir_filters"."name") ,"ir_filters"."id" DESC;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=14.44..14.44 rows=1 width=56) (actual time=0.086..0.087 rows=0 loops=1)
Sort Key: (COALESCE(ir_filters__name.value, (ir_filters.name)::text)), ir_filters.id DESC
Sort Method: quicksort Memory: 25kB
-> Nested Loop Left Join (cost=8.86..14.43 rows=1 width=56) (actual time=0.080..0.081 rows=0 loops=1)
Join Filter: (ir_filters.id = ir_filters__name.res_id)
-> Bitmap Heap Scan on ir_filters (cost=8.86..12.87 rows=1 width=36) (actual time=0.079..0.080 rows=0 loops=1)
Recheck Cond: ((((model_id)::text = 'account.move'::text) AND (user_id = 2)) OR (((model_id)::text = 'account.move'::text) AND (user_id IS NULL)))
Filter: (active AND ((action_id = 225) OR (action_id IS NULL)))
-> BitmapOr (cost=8.86..8.86 rows=1 width=0) (actual time=0.078..0.079 rows=0 loops=1)
-> Bitmap Index Scan on ir_filters_name_model_uid_unique (cost=0.00..4.43 rows=1 width=0) (actual time=0.075..0.075 rows=0 loops=1)
Index Cond: (((model_id)::text = 'account.move'::text) AND (user_id = 2))
-> Bitmap Index Scan on ir_filters_name_model_uid_unique (cost=0.00..4.43 rows=1 width=0) (actual time=0.002..0.002 rows=0 loops=1)
Index Cond: (((model_id)::text = 'account.move'::text) AND (user_id IS NULL))
-> Seq Scan on ir_translation ir_filters__name (cost=0.00..1.54 rows=1 width=36) (never executed)
Filter: ((value <> ''::text) AND ((type)::text = 'model'::text) AND ((name)::text = 'ir.filters,name'::text) AND ((lang)::text = 'en_US'::text))
Planning Time: 1.000 ms
Execution Time: 0.121 ms
```
I take the opportunity to add the populate for `ir.filters`,
which helped me for the above analysis.
closes odoo/odoo#99657
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
…
…
…
…
…
…
…
Odoo
Odoo is a suite of web based open source business apps.
The main Odoo Apps include an Open Source CRM, Website Builder, eCommerce, Warehouse Management, Project Management, Billing & Accounting, Point of Sale, Human Resources, Marketing, Manufacturing, ...
Odoo Apps can be used as stand-alone applications, but they also integrate seamlessly so you get a full-featured Open Source ERP when you install several Apps.
Getting started with Odoo
For a standard installation please follow the Setup instructions from the documentation.
To learn the software, we recommend the Odoo eLearning, or Scale-up, the business game. Developers can start with the developer tutorials
Languages
Python
49.6%
JavaScript
47.8%
SCSS
2%
CSS
0.3%
HTML
0.2%