如何在查询结果中添加整数唯一ID - __efficiently__?

时间:2017-03-23 11:19:20

标签: hadoop apache-spark hive apache-spark-sql hiveql

给定一个查询,select * from ...(可能是CTAS语句的一部分)

目标是添加一个额外的列ID,其中ID是一个唯一的整数。

select ... as ID,* from ...

P.S。

  • ID不必是顺序的(可能存在间隙)
  • ID可以是任意的(不必代表结果集中的特定订单)

row_number 逻辑上解决了问题 -

select row_number() over () as ID,* from ...

问题是,至少就目前而言,全局 row_number (没有分区)正在使用单个reducer(hive)/ task(spark)实现。

4 个答案:

答案 0 :(得分:1)

<强>蜂房

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

<强>火花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

答案 1 :(得分:1)

如果您使用Spark-sql,最好的办法是使用内置函数

monotonically_increasing_id

在单独的列中生成唯一的随机ID。 正如你所说,你不需要它是连续的,所以理想情况下这应该满足你的要求。

答案 2 :(得分:0)

从Manoj Kumar检查此解决方案:https://github.com/manojkumarvohra/hive-hilo

  • 创建一个有状态的UDF,它维护一个HI / LO计数器 递增序列。
  • HI值在zookeeper中保持为分布原子长。
  • HI值增加&amp;每n LO获取一次(默认为200) 迭代。
  • UDF支持单个String参数,即序列名称 用于维护zookeeper中的zNode。

用法:

FunctionName( sequenceName, lowvalue[optional], seedvalue[optional])

答案 3 :(得分:0)

查看全局唯一ID服务https://github.com/spinaki/distributed-unique-id 它也有一个码头图像,你可以快速测试。