[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) <tde@openerp.com>
This commit is contained in:
Nicolas Seinlet
2021-05-19 11:30:54 +00:00
parent 7287ce5355
commit 13ff10d8f1
+29 -23
View File
@@ -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: