我不能完全理解Hive中的分区概念。我了解什么是分区以及如何创建分区。我搞不懂的是,为什么人们要写select语句,其中包含“partition by”子句,就像这里这样:sql最近在partition上使用了row\u 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语句中定义的分区方案。那么为什么要加上它(按会话划分\u id按ts desc排序)?如果我跳过(按会话划分\u id按ts desc排序)?
1条答案
按热度按时间fslejnso1#
了解配置单元窗口和分析功能。
row-number()
是一个分析函数,它对行进行编号并要求over()
.在
over()
您可以指定将为哪个组(分区)计算它。partition by
在over
不等于partitioned by
在create表ddl中,没有任何共同点。在create table中,它表示数据的存储方式(每个分区在hive中都是一个单独的文件夹),分区表用于优化筛选或加载数据。partition by
在over()
确定计算函数的组。与select中的group by类似,但不同的是analytics函数不会更改行数。当行号越过分区边界并以1开始时,它将重新初始化
还需要行号
order by
在over()中。order by
确定行的编号顺序。如果您不指定
partition by
,行号将作为单个分区在整个数据集上工作。它将生成单个1,最大数量将等于整个数据集中的行数。表分区不影响分析函数的行为。如果您不指定
order by
,则row\ u number将按不确定的顺序对行进行编号,并且可能不同的行将在运行之间标记为1。这就是为什么您需要指定order by
. 在你的例子中,order by ts desc
意味着1将被分配给最大ts的行(对于每个会话id)。比方说,如果有三个不同的session\u id,并且在每个session中有三次单击(总共9行),那么在您的示例中,row\u number将为每个session和筛选之后的最后一次单击指定1
recent_click = 1
您将得到3行而不是最初的9行。row_number() over()
如果不使用partition by,则将按随机顺序对从1到9的所有行进行编号(每个运行可能不同),并且相同的筛选将为您提供所有3个会话中混合的8行。另请参见此答案https://stackoverflow.com/a/55909947/2700344 有关它在配置单元中如何工作的更多详细信息,在注解中还有关于表分区vs over()的类似问题。
试试这个例子,可能比读太长的解释要好:
结果:
为每个会话(分区)中具有最大时间戳的行分配1的第一行\u编号。第二行没有指定分区和顺序,将所有行从1到9编号。为什么rn2=1表示session2,而max timestamp in session=2,它应该是随机的还是非随机的?因为为了计算第一行的\u号,所有的行都是按session\u id分布的,并按timestamp desc排序,恰好行的\u号2首先收到session2(reducer在mapper准备的其他两个文件之前读取了session2),并且由于它已经被排序以计算rn1,所以rn2以相同的顺序收到行。如果不是行号1,它可能是“更随机的”。数据集越大,随机的rn2顺序看起来就越多。