配置单元-如何以最佳性能重用配置单元中的子查询

zf9nrax1  于 2021-06-26  发布在  Hive
关注(0)|答案(1)|浏览(307)

当在select语句中有一个重复多次的复杂子查询时,在配置单元中构造/编写查询的最佳方法是什么?
我最初为子查询创建了一个临时表,该表在每次运行之前都会刷新。然后我开始使用cte作为原始查询的一部分(放弃temp表)以提高可读性,并注意到性能下降。这让我很好奇,在需要重用子查询时,哪种实现方法的性能最好。
我正在处理的数据包含超过1000万条记录。下面是我使用cte编写的查询示例。

with temp as (
   select
      a.id,
      x.type,
      y.response
   from sandbox.tbl_form a
   left outer join sandbox.tbl_formStatus b
   on a.id = b.id
   left outer join sandbox.tbl_formResponse y
   on b.id = y.id
   left outer join sandbox.tbl_formType x
   on y.id = x.typeId
   where b.status = 'Completed'
)
select
   a.id,
   q.response as user,
   r.response as system,
   s.response as agent,
   t.response as owner
from sandbox.tbl_form a
left outer join (
   select * from temp x
   where x.type= 'User'
) q
on a.id = q.id
left outer join (
   select * from temp x
   where x.type= 'System'
) r
on a.id = r.id
left outer join (
   select * from temp x
   where x.type= 'Agent'
) s
on a.id = s.id
left outer join (
   select * from temp x
   where x.type= 'Owner'
) t
on a.id = t.id;
nfeuvbwi

nfeuvbwi1#

您的查询中存在问题。
1) 在cte中有三个左连接,没有on子句。这可能会导致严重的性能问题,因为没有on子句的连接是交叉连接。
2) 顺便说一句 where b.status = 'Completed' 子句将带有表b的左联接转换为内部联接,尽管仍然没有 ON 子句将a中的所有记录乘以b中的所有记录。
3) 很可能你根本不需要cte。只要正确地加入 ON 条款和使用 case when type='User' then response end +骨料使用 min() 或者 max()id :

select a.id
max(case when x.type='User' then y.response end) as user,
max(case when x.type='System' then y.response end) as system,
...

from sandbox.tbl_form a
   left outer join sandbox.tbl_formStatus b
   on a.id = b.id
   left outer join sandbox.tbl_formResponse y
   on b.id = y.id
   left outer join sandbox.tbl_formType x
   on y.id = x.typeId
   where b.status = 'Completed' --if you want LEFT JOIN add --or b.status is null
group by a.id

相关问题