hive:为什么在selects中使用partitionby?

yhqotfr8  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(390)

我不能完全理解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排序)?

fslejnso

fslejnso1#

了解配置单元窗口和分析功能。 row-number() 是一个分析函数,它对行进行编号并要求 over() .
over() 您可以指定将为哪个组(分区)计算它。 partition byover 不等于 partitioned by 在create表ddl中,没有任何共同点。在create table中,它表示数据的存储方式(每个分区在hive中都是一个单独的文件夹),分区表用于优化筛选或加载数据。 partition byover() 确定计算函数的组。与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()的类似问题。
试试这个例子,可能比读太长的解释要好:

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

为每个会话(分区)中具有最大时间戳的行分配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顺序看起来就越多。

相关问题