为子查询优化 Postgresql 查询

Posted

技术标签:

【中文标题】为子查询优化 Postgresql 查询【英文标题】:Optimizing Postgresql Query for a Subquery 【发布时间】:2020-03-18 09:57:56 【问题描述】:

我对 postgres 很陌生,这可能是一个新手问题。如何改进此查询?

三个表,campaigns 1-->M threads 1-->M messages。我有活动 ID,并且我希望所有线程及其全部个体 opensclicksreplies 计数所有相关消息,其中 opensclicks 在名为 extra 的 JSONB 字段中messages 和回复是具有 "direction"='received' 列的 messages

select "threads".*, 
count("messages"."extra"->'opens') as opens, 
count("messages"."extra"->'clicks') as clicks, 
(
    select count("messages"."id")
    from "messages" 
    where "messages"."thread_id" = "threads"."id" 
    and "messages"."direction"='received'
) as replies
from "threads" 
inner join "messages" 
on "messages"."thread_id" = "threads"."id" 
where "threads"."campaign_id" 
in ('campaign_uuid') 
group by "threads"."id"

【问题讨论】:

【参考方案1】:

认为你可以做一个条件计数:

select 
    t.id, 
    sum(jsonb_array_length(m.extra->'opens')) as opens, 
    sum(jsonb_array_length(m.extra->'clicks')) as clicks, 
    count(*) filter(where m.direction='received') as replies
from threads t
inner join messages m on m.thread_id = t.id 
where t.campaign_id = 'campaign_uuid'
group by t.id

注意事项:

如果打开和点击都是jsonb数组,可以使用jsonb_array_length()来计算它们的长度

1234563我将查询修改为只选择threads.id;如果您想要更多来自threads 的列,那么您应该在selectgroup by 子句中添加它们。

除非确实需要,否则不要在标识符周围使用双引号(在您的查询中似乎不是这种情况)

表别名使查询更易读写

【讨论】:

感谢您的详细解释。我刚刚发现我的查询是错误的。 clicksopens 是数组。即使数组中有多个项目,count(m.extra->'opens') 也会计数为 1。如何获得总计数?认为我需要 SUM。 @Rocky 。 . .这回答了您最初提出的问题。如果你有不同的问题,你应该提出一个新的问题。我还建议您包括示例数据和所需的结果。 @Rocky:您可以使用jsonb_array_length() 来计算数组中的项目数。 我现在有了所有的答案。谢谢你的帮助(y)

以上是关于为子查询优化 Postgresql 查询的主要内容,如果未能解决你的问题,请参考以下文章

禁用 PostgreSQL 查询优化?

PostgreSQL 计数查询优化

PostgreSQL 查询性能和可能的优化

PostgreSQL代码分析,查询优化部分,process_duplicate_ors

理解/优化 Postgresql 中的 SQL 查询

如何优化在 postgresql 中查询这些数据?