我有以下查询选择团队/过滤器,并计算与之匹配的关联数
select t.name, count(c.id) from teams t
left join users u on t.id = u.team_id
left join conversation_users cu on cu.user_id = u.id
left join conversations c on cu.conversation_id = c.id
group by t.id
UNION
select 'Me', count(cu.id) from conversations c
left join conversation_users cu on cu.conversation_id = c.id
where cu.user_id = 'logged in user'
UNION
select 'All', count(c.id) from conversations c
left join apps a on c.app_id = a.id
where a.id = 'current app'
UNION
select 'Unassigned', count(c.id) from conversations c
left join apps a on c.app_id = a.id
where a.id = 'current app' and c.user_id is null
我不是数据库天才,但这似乎是一种非常低效/不可扩展的方法。有没有更好的方法来实现这一目标?
目前在小型桌子上运行大约需要50ms。
我想我可以用这种方法非常快速地获取Me,All和Unsigned过滤器(大约15ms)
select
count(case when c.started then 1 end) as all,
count(case when COALESCE(c.assigned_user_id::text, c.assigned_team_id::text) is null and c.started then 1 end) as unassigned,
count(case when c.assigned_user_id = 'clt8ojxvk0000dp2fyvwq126' and c.started then 1 end) as me
from apps a
left join conversations c on c.app_id = a.id
where a.id = 'ASnYW1-RgCl0I'
我可以为团队做类似的事情并将它们合并在一起吗?
答案 0 :(得分:1)
更改为UNION ALL将是一个明显的步骤,但我们没有关于这里涉及多少行的信息,因此很难做出性能判断。
答案 1 :(得分:0)
首先,您应该分别运行每个查询以确定其中一个查询是否会降低查询速度。您应该确保on
子句中使用的所有列都已编制索引。
其次(根据David的建议),将union
更改为union all
s。
您可以简化第一个查询:
select t.name, count(cu.conversation_id)
from teams t left join
users u
on t.id = u.team_id left join
conversation_users cu
on cu.user_id = u.id
group by t.name
据推测,conversation_users
是一个联结表,因此每一行都引用一个对话。
同样,可以简化第二个查询以删除join
s:
select 'Me', count(*)
from conversation_users cu
where cu.user_id = 'logged in user'
最后两个可能会被简化为:
select 'All', count(*)
from conversations c
where c.app_id = 'current app'
select 'Unassigned', count(*)
from conversations c
where c.app_id = 'current app' and c.user_id is null
这些变化对数据模型做出(合理的)假设。
此外,您应该考虑更改数据模型,以便ID是整数,而不是字符串。使用键的连接会导致性能降低,但在这种情况下其他因素可能更为重要。