我无法完全理解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
中的over
与partitioned by
创建表DDL中的不相同,并且没有任何共同点。在create table中,这意味着如何存储数据(每个分区在hive中是一个单独的文件夹),分区表用于优化过滤或加载数据。
partition by
在over()
确定功能的确定组中。与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] 删除。
我来说两句