[IMP] website: perf - reduce SQL queries for the website menu

Render page flow:
  - Search website.page in _serve_page for requested URL
  - Check if the page is visible with `is_visible`
  - `is_visible` will get the `ir.ui.view` of the page
    Note that this is not 'cachable' as being visible depends of now() for the
    publishing date
  - Render layout which is getting the website menus
    Note that this can't be cached either as a menu visibility might also
    depends of it's website.page visibility which depends of now()
  - Checking menus `is_visible` fetch the menus pages and those pages views.

Before this commit, every level of menu hierarchy would add 2 queries.
This can be avoided by prefetching everything in once during the dispatch if we
know we will render the website menu.
In such a case, read `is_visible` on every website menus will fetch every
pages, views and menus in the lowest SQL queries possible, eg one query for
every table.

For a 3 level menus, requests goes from 20 to 12 to load a untracked page.

task-2211013
This commit is contained in:
Romain Derie
2020-03-26 18:12:47 +00:00
parent af68fcde48
commit a5a57321c7
2 changed files with 3 additions and 2 deletions
+2 -1
View File
@@ -143,7 +143,8 @@ class Website(models.Model):
# don't add child menu if parent is forbidden
if menu.parent_id and menu.parent_id in menus:
menu.parent_id._cache['child_id'] += (menu.id,)
# prefetch every website.page and ir.ui.view at once
menus.mapped('is_visible')
website.menu_id = menus and menus.filtered(lambda m: not m.parent_id)[0].id or False
# self.env.uid for ir.rule groups on menu
+1 -1
View File
@@ -113,7 +113,7 @@ class TestWebsitePerformance(UtilPerf):
menu_bb.parent_id = menu_b
menu_aa.parent_id = menu_a
self.assertEqual(self._get_url_hot_query(self.page.url), 22)
self.assertEqual(self._get_url_hot_query(self.page.url), 14)
def test_50_perf_sql_web_content(self):
# assets route /web/content/..