如何在 Presto 中没有唯一键的情况下进行全局排序
how to do global sorting without a unique key in Presto
在我的例子中,我有一些配置单元 tables,分区列 (dt) 是每个 table 包含的唯一列。
我在 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,结果不一样。我认为根本原因是我 table 缺少唯一密钥。
是否可以在 Presto 中进行没有唯一键的全局查询?
您正在计算row_number
row_number() over(ORDER BY T.dt)
并且 ORDER BY 列总是相同的 dt='2021-09-06'。在这种情况下 row_number 具有不确定的行为,并且可以将相同的数字分配给来自 运行 运行.
的不同行
您在 Hive 中总是得到相同结果的事实是一个巧合,可能您总是 运行 完全相同的拆分数量,甚至在单个映射器上,运行 是单个映射器-线程化并产生看起来像确定性的结果。 Presto 可能具有不同的并行度,它会影响先将哪些行传递给 row_number。
您可以尝试更改拆分配置中的某些内容以强制使用更多映射器或增加数据大小,您将能够重现非确定性行为,许多映射器 运行 在重负载集群上并行运行将以不同的速度执行,不同的行将传递给 row_number.
要获得确定性结果,您可以向 ORDER BY 添加一些列,这将确定行的顺序。如果您没有这样的列,则意味着您可以拥有任意数量的完整副本。
即使您没有唯一键,如果所有列都按以下顺序排序,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 行,每个行的顺序都不同 运行(假设数据集非常大,并且有许多映射器同时 运行ning,一些映射器可以完成更快,有些可能会失败并重新启动)。当然,如果你有这么小的数据集,并且总是在单进程、单线程中处理它,结果会是一样的,但一般来说,这不是数据库的工作方式。
row_number() over(ORDER BY col1, col2)
也一样
但在 row_number() over(ORDER BY col1, col2, col3)
的情况下 - 您将始终获得相同的数据集,保证。
因此,解决方案是根据需要使用尽可能多的列顺序来确定行的顺序。在最坏的情况下,如果您有完整的重复项,则应将所有列添加到 ORDER BY,重复项将一起排序,结果将是确定的。
在我的例子中,我有一些配置单元 tables,分区列 (dt) 是每个 table 包含的唯一列。
我在 hive
中执行下面的 sqlSELECT * 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,结果不一样。我认为根本原因是我 table 缺少唯一密钥。
是否可以在 Presto 中进行没有唯一键的全局查询?
您正在计算row_number
row_number() over(ORDER BY T.dt)
并且 ORDER BY 列总是相同的 dt='2021-09-06'。在这种情况下 row_number 具有不确定的行为,并且可以将相同的数字分配给来自 运行 运行.
的不同行您在 Hive 中总是得到相同结果的事实是一个巧合,可能您总是 运行 完全相同的拆分数量,甚至在单个映射器上,运行 是单个映射器-线程化并产生看起来像确定性的结果。 Presto 可能具有不同的并行度,它会影响先将哪些行传递给 row_number。
您可以尝试更改拆分配置中的某些内容以强制使用更多映射器或增加数据大小,您将能够重现非确定性行为,许多映射器 运行 在重负载集群上并行运行将以不同的速度执行,不同的行将传递给 row_number.
要获得确定性结果,您可以向 ORDER BY 添加一些列,这将确定行的顺序。如果您没有这样的列,则意味着您可以拥有任意数量的完整副本。
即使您没有唯一键,如果所有列都按以下顺序排序,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 行,每个行的顺序都不同 运行(假设数据集非常大,并且有许多映射器同时 运行ning,一些映射器可以完成更快,有些可能会失败并重新启动)。当然,如果你有这么小的数据集,并且总是在单进程、单线程中处理它,结果会是一样的,但一般来说,这不是数据库的工作方式。
row_number() over(ORDER BY col1, col2)
但在 row_number() over(ORDER BY col1, col2, col3)
的情况下 - 您将始终获得相同的数据集,保证。
因此,解决方案是根据需要使用尽可能多的列顺序来确定行的顺序。在最坏的情况下,如果您有完整的重复项,则应将所有列添加到 ORDER BY,重复项将一起排序,结果将是确定的。