diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py index 8cb742f9c..3d0e5f1f7 100644 --- a/mail_tracking/models/mail_message.py +++ b/mail_tracking/models/mail_message.py @@ -34,6 +34,16 @@ class MailMessage(models.Model): search="_search_is_failed_message", ) + # get_failed_count runs on every web client load (res.users._init_messaging) + # and filters on this flag, which only a handful of messages carry. Without a + # partial index the planner walks the failed trackings and probes mail_message + # by primary key once per tracking. Keep "IS TRUE": it is what the ORM generates + # for ("mail_tracking_needs_action", "=", True), and PostgreSQL does not use a + # plain "WHERE mail_tracking_needs_action" index for it. + _mail_tracking_needs_action_index = models.Index( + "(id) WHERE mail_tracking_needs_action IS TRUE" + ) + @api.model def get_failed_states(self): """The 'failed' states of the message""" diff --git a/mail_tracking/readme/INSTALL.md b/mail_tracking/readme/INSTALL.md index f9e4eab48..bcaa7a320 100644 --- a/mail_tracking/readme/INSTALL.md +++ b/mail_tracking/readme/INSTALL.md @@ -3,3 +3,20 @@ option) where /web/databse/selector returns a list of more than one database, then you need to add `mail_tracking` addon to wide load addons list (by default, only `web` addon), setting `--load` option. For example, `--load=web,mail,mail_tracking` + +The first update of the module after this index was added creates a partial +index on `mail_message` (`mail_message_mail_tracking_needs_action_index`). Later +updates do not build it again: Odoo keeps it while its definition does not change. + +On a database with a very large `mail_message` table that first build blocks +writes to the table while it runs (13 minutes on 122 million rows). To avoid the +lock, create the index beforehand exactly as the ORM would, with the comment it +stores on it; Odoo compares that comment with the index definition and keeps +the index when they match: + +```sql +CREATE INDEX CONCURRENTLY mail_message_mail_tracking_needs_action_index + ON mail_message (id) WHERE mail_tracking_needs_action IS TRUE; +COMMENT ON INDEX mail_message_mail_tracking_needs_action_index + IS 'INDEX (id) WHERE mail_tracking_needs_action IS TRUE'; +```