Hive:为什么要在选择中使用分区?
Hive: why to use partition by in selects?
我无法完全理解 Hive 中的分区概念。
我了解什么是分区以及如何创建分区。我无法理解的是为什么人们正在编写 select 语句,其中包含“partition by”子句,就像这里所做的那样:SQL most recent using row_number() over partition
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中指定分区键?在任何情况下,分区键都是在 table 创建期间定义的。 Select 语句将使用在 Create Table 语句中定义的分区方案。那为什么还要加上 over (partition by session_id order by ts desc)?
如果我跳过 over (partition by session_id order by ts desc) ?
了解 Hive Windowing and Analytics Functions。
row-number()
是一个分析函数,它对行进行编号并需要 over()
.
在 over()
中,您可以指定要计算的组(分区)。
over
中的 partition by
与 create table DDL 中的 partitioned by
不同,没有任何共同点。 in create table表示数据的存储方式(每个分区在hive中是一个单独的文件夹),分区table用于优化过滤或加载数据。
over()
中的partition by
决定函数计算所在的组。类似于select中的GROUP BY,不同的是分析函数不改变行数。
Row_number re-initializes 当它越过分区边界并从 1
开始时
另外 row_number 在 over() 中需要 order by
。 order by
确定行的编号顺序。
如果您不指定 partition by
,row_number 将作为单个分区处理整个数据集。它将产生单个 1 并且最大数量将等于整个数据集中的行数。 Table 分区不影响分析功能行为。
如果您不指定 order by
,则 row_number 将按 non-deterministic 顺序对行进行编号,并且可能不同的行将标记为 运行 运行 中的 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 行混合.
另请参阅此答案 了解它在 Hive 中的工作原理的更多详细信息,评论中也有关于 table partition 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
首先 row_number 将 1 分配给每个会话(分区)中具有最大时间戳的行。第二个 row_number 没有指定分区和顺序编号所有行从 1 到 9。为什么 rn2=1 用于 session2 和 max timestamp in session=2,它应该是随机的还是不是?因为首先计算 row_number,所有行都按 session_id 分配并按时间戳 desc 排序,碰巧 row_number2 首先收到 session2(它在由 准备的其他两个文件之前被 reducer 读取)映射器)并且因为它已经为 rn1 的计算排序,rn2 以相同的顺序接收行。如果不是 row_number1,它可能会“更随机”。数据集越大,rn2顺序看起来越随机。
我无法完全理解 Hive 中的分区概念。 我了解什么是分区以及如何创建分区。我无法理解的是为什么人们正在编写 select 语句,其中包含“partition by”子句,就像这里所做的那样:SQL most recent using row_number() over partition
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中指定分区键?在任何情况下,分区键都是在 table 创建期间定义的。 Select 语句将使用在 Create Table 语句中定义的分区方案。那为什么还要加上 over (partition by session_id order by ts desc)? 如果我跳过 over (partition by session_id order by ts desc) ?
了解 Hive Windowing and Analytics Functions。
row-number()
是一个分析函数,它对行进行编号并需要 over()
.
在 over()
中,您可以指定要计算的组(分区)。
over
中的 partition by
与 create table DDL 中的 partitioned by
不同,没有任何共同点。 in create table表示数据的存储方式(每个分区在hive中是一个单独的文件夹),分区table用于优化过滤或加载数据。
over()
中的partition by
决定函数计算所在的组。类似于select中的GROUP BY,不同的是分析函数不改变行数。
Row_number re-initializes 当它越过分区边界并从 1
另外 row_number 在 over() 中需要 order by
。 order by
确定行的编号顺序。
如果您不指定 partition by
,row_number 将作为单个分区处理整个数据集。它将产生单个 1 并且最大数量将等于整个数据集中的行数。 Table 分区不影响分析功能行为。
如果您不指定 order by
,则 row_number 将按 non-deterministic 顺序对行进行编号,并且可能不同的行将标记为 运行 运行 中的 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 行混合.
另请参阅此答案
试试这个例子,它可能比阅读太长的解释更好:
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 in session=2,它应该是随机的还是不是?因为首先计算 row_number,所有行都按 session_id 分配并按时间戳 desc 排序,碰巧 row_number2 首先收到 session2(它在由 准备的其他两个文件之前被 reducer 读取)映射器)并且因为它已经为 rn1 的计算排序,rn2 以相同的顺序接收行。如果不是 row_number1,它可能会“更随机”。数据集越大,rn2顺序看起来越随机。