如何通过多个子查询和联接来缩短加载时间?

时间:2019-01-14 16:49:48

标签: postgresql postgresql-performance

我有一个查询来查找哪个v_address属于哪个v_group,以及何时创建v_address。但是,每个v_group有时都处于活动状态和非活动状态,并且都有日期。因此,我编写了查询以查找这些更改的时间段。

我的问题是我的查询花了很长时间运行,因为它具有多个子查询和联接。

有人有更好的主意来缩短加载数据吗?
  我在identifier = 81下面附加了查询,以进行较小的测试。为了获得最终结果,我将需要检索超过10万个ID的数据。

我试图将内部联接更改为左联接,但是它丢失了空值,并且仍然花费很长时间来检索数据。

with v_address as (
    select id, v_group_id, created_at
    from prod.venue_address --different schema and table. v_address.v_group_id can have multiple v_address.id
    group by 1,2,3
    order by 3 asc
    ),
v_group as (
    select identifier, final_status, created_at
    from dwh.venue_address_archive
    where identifier = 81
    group by 1,2,3
    order by 3 asc
    ),
filtering as (
    select identifier, created_at,
    case when sum(case when final_state = 'active' then 1 else 0 end) > 0 then 'active' else 'inactive' end as filtered_status --This filters either of active or inactive
    from v_group
    group by 1,2
    order by 2 asc
    ),
prev as (
    select identifier, created_at, filtered_status,
    lag(case when filtered_status = 'active' then 'active' else 'inactive' end) over (partition by identifier order by created_at) = filtered_status as is_prev_status
    from filtering
    group by 1,2,3
    ),
periods as (
    select identifier, filtered_status, created_at, is_prev_status,
    sum(case when is_prev_status = true then 0 else 1 end) over (order by identifier, created_at) as period
    from prev
    group by 1,2,3,4
    ),
islands_gaps_start as (
    select identifier, period, min(created_at) as start_at
    from periods
    group by 2,1
    ),
islands_gaps as (
    select identifier, period, start_at,
    lead(start_at) over (partition by identifier order by period) as end_at
    from islands_gaps_start
    )
select vg.identifier as "vg_id", p.created_at as "vg_created_at", p.filtered_status as "status", p.is_prev_status, p.period, va.id as "va_id", g.start_at, g.end_at
from v_address va
left join v_group vg
on va.venue_id = vg.identifier
inner join filtering f
on vg.identifier = f.identifier
inner join prev pr
on pr.filtered_status = f.filtered_status
inner join periods p
on p.filtered_status = pr.filtered_status
inner join islands_gaps_start gs
on p.period = gs.period
inner join islands_gaps g
on gs.start_at = g.start_at
group by 6,1,2,3,4,5,7,8
order by 2 asc

我已经有了示例identifier = 81的输出,但是我必须为100k以上的标识符运行该查询,因此,我正在寻找可以缩短查询时间的任何建议。

0 个答案:

没有答案