【问题标题】:Need assistance in rewriting this query在重写此查询时需要帮助
【发布时间】:2019-09-15 23:07:16
【问题描述】:

我们在生产环境中有这个查询,每天运行 它做了很多连接,还使用了 hive 中的窗口函数

我们尝试添加一些设置选项,但这并没有太大帮助

结构是这样的 -

SELECT
        C.f1, C.f2, A.f2 ...
FROM (
    SELECT * FROM (
        SELECT T1.*, B.atid, B.a_id,
        ROW_NUMBER() OVER (PARTITION BY T1.wtid, B.atid ORDER BY T1.b_ts DESC) AS RANK_
        FROM T1 AS T1
        JOIN T5 ON T1.t_dt = T5.t_dt
        JOIN T2 B ON T1.wtid = B.wtid and T1.b_ts = B.b_ts
        LEFT OUTER JOIN (SELECT p_cd FROM T3 WHERE PV_TY_CD = 'ORIG_CD') PV
        ON T1.TYP = PV.p_cd
        WHERE T1.state not in ("INVALID")
        AND T1.evt_name NOT IN ('INACTIVE','DORMANT')
        AND ISNULL(PV.p_cd)
    ) T
    WHERE T.rank_ = 1
) A

JOIN (SELECT *, row_number() over (partition by ac_id order by b_ts desc) rank_  
      FROM T4
      WHERE event not in ('CT','UPD')
     ) AS C
  ON A.a_id = C.a_id
AND A.atid = C.ac_id
AND C.rank_ = 1
JOIN T6 ON C.t_dt = T6.t_dt
  • 由于我不能忽略任何表(和连接),我的方法是使用聚合函数 max 将窗口函数替换为另一个连接,但我无法重写它。
  • 另外,我不确定这是否肯定有助于提高性能,因此任何指导都会对我们有所帮助。

【问题讨论】:

  • 如果您没有在 Tez 上运行它,请尝试一下。查询越复杂,Tez 的改进就越大。如果无法改进查询,请调整并行性:stackoverflow.com/a/48296562/2700344

标签: sql hive query-optimization hiveql


【解决方案1】:

分析函数通常比使用 select max 的连接执行得更好,因为在分析函数和 row_number 计算由 partition by 并行化的情况下,您只读取同一个表一次。

尝试重新组合连接和过滤。

加入

LEFT OUTER JOIN (SELECT p_cd FROM T3 WHERE PV_TY_CD = 'ORIG_CD') PV
        ON T1.TYP = PV.p_cd

where 条件 ISNULL(PV.p_cd) 正在减少 T1 中的一些行。 这些条件也一样:

WHERE T1.state not in ("INVALID")
        AND T1.evt_name NOT IN ('INACTIVE','DORMANT')

将此连接移动到子查询中,如果它过滤了一个 lo,这可能有助于在所有其他连接和 row_number() 之前减少 T1 中的数据集:

(select T1.* from T1 
             left join (SELECT p_cd FROM T3 WHERE PV_TY_CD = 'ORIG_CD') PV 
                       ON T1.TYP = PV.p_cd 
 where T1.state not in ("INVALID")
        AND T1.evt_name NOT IN ('INACTIVE','DORMANT')
        AND ISNULL(PV.p_cd)
) as T1 

第一个 row_number 仅在 T1 和 B 表上计算:

PARTITION BY T1.wtid, B.atid ORDER BY T1.b_ts DESC

考虑在row_number过滤器之后加入T5表,如果这个连接很重,并且row_number过滤器正在减少数据集,那么在子查询中再次用过滤器包裹row_number并连接用T5过滤的子查询。

(--filtered by row_number
select * from
(
 SELECT T1.*, B.atid, B.a_id,
        ROW_NUMBER() OVER (PARTITION BY T1.wtid, B.atid ORDER BY T1.b_ts DESC) AS RANK_
  from
    (select T1.* from T1 
                 left join (SELECT p_cd FROM T3 WHERE PV_TY_CD = 'ORIG_CD') PV 
                           ON T1.TYP = PV.p_cd 
     where T1.state not in ("INVALID")
            AND T1.evt_name NOT IN ('INACTIVE','DORMANT')
            AND ISNULL(PV.p_cd)
    ) as T1 JOIN T2 B ON T1.wtid = B.wtid and T1.b_ts = B.b_ts
) T WHERE T.rank_ = 1
) T --filtered
JOIN T5 ON T1.t_dt = T5.t_d  

这可能会有所帮助,具体取决于您的数据。

另请阅读:https://stackoverflow.com/a/51061613/2700344 和此:https://stackoverflow.com/a/51061613/2700344

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多