蜂巢:为什么要在选择中使用分区?

迈阿密滩

我无法完全理解Hive中的分区概念。我了解什么是分区以及如何创建它们。我无法理解的是为什么人们在编写具有“ partition by”子句的select语句,就像在这里所做的那样:SQL最近在分区上使用row_number()

SELECT user_id, page_name, recent_click
FROM (
  SELECT user_id,
         page_name,
         row_number() over (partition by session_id order by ts desc) as recent_click
  from clicks_data
) T
WHERE recent_click = 1

为什么在selects中指定分区键?无论如何,分区键是在表创建期间定义的。Select语句将使用Create Table语句中定义的分区方案。那为什么还要加上这个(按ts desc按session_id顺序划分)如果我跳过(按ts desc按session_id顺序分区)怎么办?

左连接

阅读有关Hive窗口和分析功能的信息

row-number()是一种分析功能,可对行进行编号并要求over()

在中,over()您可以指定要计算的组(分区)。partition by中的overpartitioned by创建表DDL中的不相同,并且没有任何共同点。在create table中,这意味着如何存储数据(每个分区在hive中是一个单独的文件夹),分区表用于优化过滤或加载数据。

partition byover()确定功能确定组中。与select中的GROUP BY类似,但区别在于分析功能不会更改行数。
Row_number越过分区边界并从1开始时会重新初始化

同样order by在over()中需要row_number order by确定行编号的顺序。

如果未指定partition by,则row_number将作为单个分区在整个数据集上工作。它将产生单个1,并且最大数目将等于整个数据集中的行数。表分区不会影响分析功能的行为。

如果未指定order by,则row_number将以不确定的顺序对行编号,并且可能每次运行都将不同的行标记为1。这就是为什么您需要指定order by在您的示例中,order by ts desc意味着会将1分配给最大ts的行(对于每个session_id)。

假设,如果每个会话中有三个不同的session_id和三个不同的ts(总共9行),那么示例中的row_number将为每个会话的最后一次点击分配1,经过过滤后,recent_click = 1您将获得3行而不是最初的9行。row_number() over()如果不进行分区,则将按随机顺序对所有行从1到9进行编号(每次运行可能会有所不同),并且相同的过滤条件将为您提供来自所有3个会话的8行。

另请参阅此答案https://stackoverflow.com/a/55909947/2700344,以了解其在Hive中如何工作的更多详细信息,注释中还存在关于表分区与over()的类似问题。

试试这个例子,可能比阅读太长的解释更好:

with clicks_data as (
select stack (9, 
--session1            
1, 1, 'page1', '2020-01-01 01:01:01.123',
1, 1, 'page1', '2020-01-01 01:01:01.124',
1, 1, 'page2', '2020-01-01 01:01:01.125',
--session2            
1, 2, 'page1', '2020-01-01 01:02:02.123',
1, 2, 'page2', '2020-01-01 01:02:02.124',
1, 2, 'page1', '2020-01-01 01:02:02.125',
--session 3           
1, 3, 'page1', '2020-01-01 01:03:01.123',
1, 3, 'page2', '2020-01-01 01:03:01.124',
1, 3, 'page1', '2020-01-01 01:03:01.125'                          
    ) as(user_id, session_id, page_name, ts)
)


    SELECT
         user_id
        ,session_id
        ,page_name
        ,ts
        ,ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY ts DESC) AS rn1
        ,ROW_NUMBER() OVER() AS rn2 
    FROM clicks_data

结果:

user_id session_id  page_name   ts                     rn1  rn2
1        2          page1      2020-01-01 01:02:02.125  1   1
1        2          page2      2020-01-01 01:02:02.124  2   2
1        2          page1      2020-01-01 01:02:02.123  3   3
1        1          page2      2020-01-01 01:01:01.125  1   4
1        1          page1      2020-01-01 01:01:01.124  2   5
1        1          page1      2020-01-01 01:01:01.123  3   6
1        3          page1      2020-01-01 01:03:01.125  1   7
1        3          page2      2020-01-01 01:03:01.124  2   8
1        3          page1      2020-01-01 01:03:01.123  3   9
     

在每个会话(分区)中,第一个row_number分配1到具有最大时间戳的行。第二个未指定分区和顺序的row_number编号为从1到9的所有行。为什么rn2 = 1代表session2,而max timestamp代表session = 2,是否应该是随机的?因为为了计算第一个row_number,所有行均按session_id分配并按时间戳记desc排序,因此发生了row_number2首先接收session2的情况(由reducer读取,然后由mapper准备的其他两个文件),并且由于已经被排序以计算rn1, rn2以相同顺序接收行。如果不是row_number1,则可能是“更加随机”。数据集越大,rn2阶将越随机。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章