我应该在这种情况下使用子查询吗?

时间:2018-05-04 02:21:05

标签: sql hive

我正在使用Apache Hive,我有这样的查询:

SELECT CASE type WHEN 'a' THEN 'A'
                 WHEN 'b' THEN 'B'
                 ELSE 'C'
            END AS map_type
       ,COUNT(user_id) AS count
FROM user_types
GROUP BY CASE type WHEN 'a' THEN 'A'
                 WHEN 'b' THEN 'B'
                 ELSE 'C'
            END
;

如您所见,我需要按map_type字段对结果进行分组,该字段以复杂的方式计算。在我的情况下,CASE WHENSELECT中的GROUP BY部分会被计算两次吗?如果我使用下面的子查询,它会更有效吗?

SELECT map_type
       ,COUNT(user_id) AS count
FROM (
       SELECT CASE type WHEN 'a' THEN 'A'
                        WHEN 'b' THEN 'B'
                        ELSE 'C'
                   END AS map_type
              ,user_id
       FROM user_types
     ) a
GROUP BY map_type;

3 个答案:

答案 0 :(得分:1)

第二个查询(涉及子查询)可能更高效。这是基于Hive的解释计划的解释,并运行这些查询几次。

查询1(没有子查询)的解释计划有以下部分:

Group By Operator [GBY_2]
                     aggregations:["count(user_id)"]
                     keys:CASE (type) WHEN ('a') THEN ('A') WHEN ('b') THEN ('B') ELSE ('C') END (type: string)

另一方面,查询2(带子查询)的相同部分包含:

Group By Operator [GBY_3]
                     aggregations:["count(_col1)"]
                     keys:_col0 (type: string)

根据计划,看起来查询2的工作量略少。

还对虚拟数据进行了测试,并获得了这些执行时间。

Query 1: (1st time) 6.43 s, (2nd time) 5.92 s, (3rd time): 4.30s
Query 2: (1st time) 0.82 s, (2nd time) 1.29 s, (3rd time): 1.03s

查询2在所有情况下都完成得更快。

答案 1 :(得分:0)

进行聚合的费用涉及阅读大量数据。然后对其进行排序或对其进行散列以将密钥组合在一起。然后引擎需要处理数据并计算计数。

在所有数据移动的上下文中,一次或两次调用case表达式是否毫无意义。别担心。如果有额外的工作,那么与其他需要为查询完成的工作相比,它是微不足道的。

我还认为Hive支持GROUP BY中的列别名,但我可能会弄错。

答案 2 :(得分:0)

case case语句在你的情况下是无害的,但如果你打算使用子查询可能会增加时间

你可以继续

SELECT CASE type WHEN 'a' THEN 'A'
                 WHEN 'b' THEN 'B'
                 ELSE 'C'
            END AS map_type
       ,COUNT(user_id) AS count
FROM user_types
GROUP BY CASE type WHEN 'a' THEN 'A'
                 WHEN 'b' THEN 'B'
                 ELSE 'C'
            END
;