在大型 (50 GB) 数据集上没有 Partition BY 子句的 Hive Window 函数 ROW_NUMBER 非常慢。有没有更好的优化方法?

Hive Window Function ROW_NUMBER without Partition BY Clause on a large (50 GB) dataset is very slow. Is there a better way to optimize?

我有一个包含 5000 万条记录的 HDFS 文件,原始文件大小为 50 GB。

我正在尝试将其加载到配置单元 table 中,并在加载时使用以下内容为所有行创建唯一 ID。我正在使用 Hive 1.1.0-cdh5.16.1.

row_number() 超过(按 event_id、user_id、时间戳排序)作为 id

在执行过程中,我看到在 reduce 步骤中分配了 40 个 reducer。 39 个 Reducer 的平均时间大约是 2 分钟,而最后一个 reducer 大约需要 25 分钟,这显然让我相信大部分数据都是在一个 reducer 中处理的。

我怀疑 Order By 子句是此行为的原因并尝试了以下操作,

row_number() over() as id

然而,我看到了相同的行为。

想到Map Reduce Paradigm,我觉得如果我们不指定Partition BY Clause,数据必须在一个reducer(非分布式)中处理才能看到所有行并附加正确的行号。对于没有分区依据子句或偏斜列分区依据的任何 Window 函数都是如此。

现在,我的问题是,当我们必须避免 Partition BY 子句时,我们如何规避这个问题并优化 window 函数?

您可以使用 UUID:

select java_method('java.util.UUID','randomUUID')

在您的 system/workflow 中生成的 UUID 在其他一些系统中也是唯一的,因为 UUID 是全局唯一的。 UUID 完全分布式且运行速度快。

在 Hive 3.x 中还有 SURROGATE_KEY 函数,您可以在 DDL

中使用它

而不是按 sort bycluster by

排序

@leftjoin's 对于这个用例,建议非常有效(非常感谢!)。它不涉及 Reduce 步骤,工作在不到 3 分钟的时间内完成。我测试过,它确实产生了唯一的 ID。将检查底层代码,因为即使有 500 多个映射器,它也能够生成唯一的 ID,这非常有趣。

由于我使用的是 Hive 1.1,因此无法尝试 SURROGATE_KEY

很遗憾,@Strick's 建议没有用,但感谢分享。使用 Cluster By 不会产生唯一 ID。所有行都标记为 1,因为我的 cluster by 子句具有自然键。 Sort By 行为在结果和性能方面与 Order By 行为相似(32 分钟完成)。也许数据是通过一个缩减器汇集的,这意味着在这种情况下排序依据等同于排序依据。 (虽然我不确定)

仍在寻找 Window 可能没有 Partition By Clause 但应该分发的函数的解决方案