如何优化 2 个各有 300 GB 数据的大表和一个有 250 GB 数据的表的左连接

问题描述 投票:0回答:1

我有 3 个表,其中 2 个表构建在 2 个不同的目录中,例如 AWS 上的 s1/ 和 s2/ 作为 parquet 文件,每个目录有 300 个文件。该分布基于 0-299 之间的密钥。

现在来到 3 个表,这是一个非常大的表,具有相同的密钥。但连接列不同,所谓的键仅源自连接列。

我有 2 组问题:

  1. 我应该做哪些spark sql优化来将这两个表加载到内存中并与s1然后s2执行大表的左连接。
  2. 如何调优 Spark SQL 查询的性能。

Spark版本:3.3.2

apache-spark apache-spark-sql left-join sparkcore
1个回答
0
投票

从注释中放下一些实际的sql。给定一个唯一的行id字段“row_id”和一个分布字段“dist_id”,其中dist_id表示一个好的数据分区处理元素(它可以从其他字段生成/派生), sql 'one' 连接表视图 'o0' 为:

select * from one -- has row_id, dist_id

以及与主表的连接:

select o.*, m.* from main m join o0 o on m.o_row_id = o.row_id

您可以使用以下命令创建视图“o1”:

select * from (

  select * from one -- has row_id, dist_id
  distribute by dist_id
  
)
order by row_id

你的主sql变成:

select o.*, m.* from main m join o1 o on m.o_row_id = o.row_id
distribute by m.dist_id

在 3.5 上,你可能只需要让 'o0' 使用“distribute by dist_id”,它似乎成功地将它转换为一个非常接近的执行计划。对于此类查询,3.5 仍然会更快,但 3.5 之前的这种方法模拟了 3.5 可以执行的转换。

这会首先强制按 dist_id 进行交换分区(在您的 other SO 中,您希望这等于您的 300 个分区),然后按 row_id,对 row_id 进行排序并使用 BroadcastExchange 散列连接表,而不是使用过滤整个视图。

在应用程序中,我正在开发带有“o”的 3.4.1,将在 9 分 15 秒内运行 22 个连接(在 4 核盒子上,不是相关的),3.5.0 在 3 分 50 秒内运行。使用“o1”方法在 3.4.1 上得到 5m16s,而 3.5.0 仍然是 3m50s。

(这种方法可能很适合您的其他问题)

© www.soinside.com 2019 - 2024. All rights reserved.