如何在没有Presto中的唯一密钥的情况下进行全局排序



在我的例子中,我有一些配置单元表,分区列(dt(是每个表唯一包含的列。

我在hive 中执行下面的sql

SELECT * FROM (
SELECT row_number() over(ORDER BY T.dt) as row_num,T.* FROM 
(select * from ods.test_table where dt='2021-09-06') as T) TT 
WHERE TT.row_num BETWEEN 1 AND 10

我每次都得到同样的结果。

但是我在Presto中执行sql,结果不一样。我认为根本原因是我的表缺少一个唯一的键。

在Presto中是否可以在没有唯一密钥的情况下进行全局查询?

您正在计算行数

row_number() over(ORDER BY T.dt)

ORDER BY列总是相同的dt="2021-09-06"。在这种情况下,row_number具有不确定性行为,可以在不同的运行中为不同的行分配相同的编号。

在Hive中总是得到相同的结果,这是一个巧合,可能你总是以完全相同的分割数运行,甚至在单个映射器上运行,该映射器运行单线程并产生看起来具有确定性的结果。Presto可能具有不同的并行性,它会影响哪些行首先传递给row_number。

您可以尝试更改拆分配置中的某些内容,以强制更多的映射器或增加数据大小,并且您将能够再现非确定性行为,在负载过重的集群上并行运行的许多映射器将以不同的速度执行,并且不同的行将传给row_number。

要获得确定性结果,可以向ORDERBY添加一些列,ORDERBY将确定行的顺序。如果没有这样的列,则意味着可以有任意数量的完全重复项。

即使您没有唯一的键,如果所有列的顺序为.,row_number也会产生确定性结果

考虑这个数据集:

Col1 Col2 Col3
1    1    2
1    1    2
1    1    3
1    1    3

row_number() over(ORDER BY col1) as rn可以在每次运行时生成所有4行,顺序不同(假设数据集非常大,并且有许多映射程序同时运行,有些映射程序可以更快地完成,有些则可能失败并重新启动(。当然,如果你有一个这么小的数据集,并且总是在单进程、单线程中处理它,结果会是一样的,但总的来说,这不是数据库的工作方式。

row_number() over(ORDER BY col1, col2)也是如此

但在row_number() over(ORDER BY col1, col2, col3)-的情况下,您将始终获得相同的数据集,这是有保证的。

因此,解决方案是根据需要按列使用尽可能多的顺序来确定行的顺序。在最坏的情况下,如果有完整的重复项,则应将所有列添加到ORDER BY中,重复项将一起排序,结果将是确定的。

相关内容

最新更新