给定一个查询,select * from ...
(这可能是 CTAS 语句的一部分)
目标是添加一个额外的列 ID
,其中 ID
是一个唯一的整数。
select ... as ID,* from ...
附言
ID
不必是连续的(可能有间隙)- ID 可以是任意的(不必代表结果集中的特定顺序)
row_number逻辑上解决了问题-
select row_number() over () as ID,* from ...
问题是,至少目前,全局row_number(没有partition by)正在使用单个reducer (hive)/task (spark) 实现。
最佳答案
hive
set mapred.reduce.tasks=1000;
set hivevar:buckets=10000;
hivevar:buckets
相对于 reducer 的数量 (mapred.reduce.tasks
) 应该足够高,因此行将在 reduce 之间均匀分布。
select 1 + x + (row_number() over (partition by x) - 1) * ${hivevar:buckets} as id
,t.*
from (select t.*
,abs(hash(rand())) % ${hivevar:buckets} as x
from t
) t
spark-sql
select 1 + x + (row_number() over (partition by x) - 1) * 10000 as id
,t.*
from (select t.*
,abs(hash(rand())) % 10000 as x
from t
) t
同时适用于 hive 和 spark-sql
rand()
用于生成良好的分布。
如果您的查询中已经有一个具有良好分布的列/列组合(可能是唯一的,不是必须的),您可以改用它,例如-
select 1 + (abs(hash(col1,col)) % 10000)
+ (row_number() over (partition by abs(hash(col1,col)) % 10000) - 1) * 10000 as id
,t.*
from t
关于hadoop - 如何为查询结果添加一个整数唯一 ID - __efficiently__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42974548/