加速联盟查询

时间:2016-07-10 11:38:29

标签: sql postgresql

我有以下查询选择团队/过滤器,并计算与之匹配的关联数

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'

我可以为团队做类似的事情并将它们合并在一起吗?

2 个答案:

答案 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是整数,而不是字符串。使用键的连接会导致性能降低,但在这种情况下其他因素可能更为重要。