如何在查询结果中添加整数唯一 id - __efficiently__?
Posted
技术标签:
【中文标题】如何在查询结果中添加整数唯一 id - __efficiently__?【英文标题】:How to add an integer unique id to query results - __efficiently__? 【发布时间】:2017-03-23 11:19:19 【问题描述】:给定一个查询,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 2.2 开始,您可以生成 UUID 而不是序列 - issues.apache.org/jira/browse/HIVE-12721 而且由于 Hive UUID 函数只是调用java.util.UUID.randomUUID().toString()
你应该能够在任何 Hive 版本中使用 reflect
做类似的事情 > github.com/apache/hive/blob/master/ql/src/java/org/apache/…
去过那里,做到了:-)。 UUID 是 36 个字节。 INT 的 4 个或 BIGINT 的 8 个。您在存储和您执行的任何操作中为它付费 - WHERE、GROUP BY、JOIN、ORDER BY 等。
36 个字节为 STRING,但只有 16 个字节为 BINARY(尽管转换为 Hive BINARY 需要 UDF)。你已经得到了你所支付的,即对于一个非常大的数据集,32 位随机值的“单一性”是值得怀疑的。与穷人 CRC32 与繁琐的加密 MD5 或 SHA1 一样的困境......
【参考方案1】:
蜂巢
set mapred.reduce.tasks=1000;
set hivevar:buckets=10000;
hivevar:buckets
相对于 reducer 的数量 (mapred.reduce.tasks
) 应该足够高,因此行将在 reducer 之间均匀分布。
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
【讨论】:
旁注:为什么要散列一个随机值?由于散列是确定性的,这不会改变碰撞的概率...... 如果您有已知分布良好的列,您可以使用它,但要注意使用可能会出现偏差的值。【参考方案2】:如果您使用的是 Spark-sql,最好的办法是使用内置函数
monotonically_increasing_id
在单独的列中生成唯一的随机 id。 正如您所说,您不需要它是连续的,因此理想情况下这应该足以满足您的要求。
【讨论】:
【参考方案3】:查看 Manoj Kumar 的解决方案:https://github.com/manojkumarvohra/hive-hilo
创建了一个有状态的 UDF,它维护一个 HI/LO 计数器 增加序列。 HI 值在 zookeeper 中保持为分布式原子长。 HI 值每 n 个 LO 递增并获取(默认为 200) 迭代。 UDF 支持单个字符串参数,即序列名称 用于维护 zookeeper 中的 zNode。用法:
FunctionName( sequenceName, lowvalue[optional], seedvalue[optional])
【讨论】:
【参考方案4】:查看这个全球唯一 ID 服务https://github.com/spinaki/distributed-unique-id 它也有一个 docker 镜像,你可以快速测试。
【讨论】:
以上是关于如何在查询结果中添加整数唯一 id - __efficiently__?的主要内容,如果未能解决你的问题,请参考以下文章
将 _id 从 ObjectId 更改为正常的唯一自动增量整数
Mongoose 在结果的 _id 字段中返回“new ObjectId”
Mongoose.js 除了 _id & __v 默认来自查询结果