From 13ff10d8f13d98c797bca387a79caa2f8d0a0ed6 Mon Sep 17 00:00:00 2001 From: Nicolas Seinlet Date: Mon, 10 May 2021 13:27:48 +0000 Subject: [PATCH] [IMP] mail: better join improve query execution time - using join on required fields ease PostgreSQL planner guessing - skip useless join, the fastest code is the not executed one - skip dynamic `or` insertion and replace with a union all in CTE - replacing `where exists` with a join is then possible - a bit of alignment from some s to some ms execution time. Submit an "Apply for a job" on website , goes from `"POST /website_form/hr.applicant HTTP/1.0" 200 - 182 2.649 0.106` without this patch, to `"POST /website_form/hr.applicant HTTP/1.0" 200 - 185 0.492 0.107` when this patch is applied closes odoo/odoo#71028 X-original-commit: 783280375ff04955978a14f007f96d6c4d7443b1 Signed-off-by: Thibault Delavallee (tde) --- addons/mail/models/mail_followers.py | 52 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py index 9dc23cb713e..8ad6b09a201 100644 --- a/addons/mail/models/mail_followers.py +++ b/addons/mail/models/mail_followers.py @@ -105,33 +105,39 @@ class Followers(models.Model): query = """ SELECT DISTINCT ON (pid) * FROM ( WITH sub_followers AS ( - SELECT fol.id, fol.partner_id, subtype.internal - FROM mail_followers fol - RIGHT JOIN mail_followers_mail_message_subtype_rel subrel - ON subrel.mail_followers_id = fol.id - RIGHT JOIN mail_message_subtype subtype - ON subtype.id = subrel.mail_message_subtype_id - WHERE subrel.mail_message_subtype_id = %%s AND fol.res_model = %%s AND fol.res_id IN %%s + SELECT fol.partner_id, + coalesce(subtype.internal, false) as internal + FROM mail_followers fol + JOIN mail_followers_mail_message_subtype_rel subrel ON subrel.mail_followers_id = fol.id + JOIN mail_message_subtype subtype ON subtype.id = subrel.mail_message_subtype_id + WHERE subrel.mail_message_subtype_id = %s + AND fol.res_model = %s + AND fol.res_id IN %s + + UNION ALL + + SELECT id, + FALSE + FROM res_partner + WHERE id=ANY(%s) ) SELECT partner.id as pid, - partner.active as active, partner.partner_share as pshare, - users.notification_type AS notif, array_agg(groups.id) AS groups - FROM res_partner partner - LEFT JOIN res_users users ON users.partner_id = partner.id AND users.active - LEFT JOIN res_groups_users_rel groups_rel ON groups_rel.uid = users.id - LEFT JOIN res_groups groups ON groups.id = groups_rel.gid - WHERE EXISTS ( - SELECT partner_id FROM sub_followers - WHERE sub_followers.partner_id = partner.id - AND (coalesce(sub_followers.internal, false) <> TRUE OR coalesce(partner.partner_share, false) <> TRUE) - ) %s - GROUP BY partner.id, users.notification_type + partner.active as active, + partner.partner_share as pshare, + users.notification_type AS notif, + array_agg(groups_rel.gid) AS groups + FROM res_partner partner + LEFT JOIN res_users users ON users.partner_id = partner.id + AND users.active + LEFT JOIN res_groups_users_rel groups_rel ON groups_rel.uid = users.id + JOIN sub_followers ON sub_followers.partner_id = partner.id + AND NOT (sub_followers.internal AND partner.partner_share) + GROUP BY partner.id, + users.notification_type ) AS x ORDER BY pid, notif -""" % ('OR partner.id IN %s' if pids else '') - params = [subtype_id, records._name, tuple(records.ids)] - if pids: - params.append(tuple(pids)) +""" + params = [subtype_id, records._name, tuple(records.ids), list(pids) or []] self.env.cr.execute(query, tuple(params)) res = self.env.cr.fetchall() elif pids: