Spark3 新特性之DPP

Spark3 新特性之DPP

DPP

DPP(Dynamic Partition Pruning,动态分区剪裁),它指的是在星型数仓的数据关联场景中,可以充分利用过滤之后的维度表,大幅削减事实表的数据扫描量,从整体上提升关联计算的执行性能。

分区剪裁

在星型(Start Schema)数仓中,我们有两张表,一张是订单表 orders,另一张是用户表 users。订单表是事实表(Fact),而用户表是维度表(Dimension)。业务需求是统计所有头部用户贡献的营业额,并按照营业额倒序排序。

// 订单表orders关键字段
userId, Int
itemId, Int
price, Float
quantity, Int

// 用户表users关键字段
id, Int
name, String
type, String //枚举值,分为头部用户和长尾用户
-- 查询sql
select (orders.price * order.quantity) as income, users.name
from orders inner join users on orders.userId = users.id
where users.type = ‘Head Usergroup by users.name
order by income desc

由于查询语句中事实表(orders)上没有过滤条件,Spark SQL 全表扫描,维度表(users)上有过滤条件 users.type = ‘Head User’,Spark SQL 可以谓词下推,把过滤操作下推到数据源之上,来减少必需的磁盘 I/O 开销。

虽然谓词下推已经很给力了,但如果用户表支持分区剪裁(Partition Pruning),I/O 效 率的提升就会更加显著。那什么是分区剪裁呢?实际上,分区剪裁是谓词下推的一种特例,它指的是在分区表中下推谓词,谓词是分区目录。分区表是通过指定分区键,然后使用 partitioned by 语句创建的数据表,或者是使用 partitionBy 语句存储的列存文件(如 Parquet、ORC 等)。

分区表分不同的目录存储数据。假设用户表是分区表,且以 type 字段作为分区键,那么用户表会有两个子目录,分别是“Head User”和“Tail User”。

**如果过滤谓词中包含分区键,那么 Spark SQL 对分区表做扫描的时候,是完全可以跳过(剪掉)不满足谓词条件的分区目录,这就是分区剪裁。**例如,在我们的查询语句中,用户表的过滤谓词是“users.type = ‘Head User’”。假设用户表是分区表,那么对于用户表的数据扫描,Spark SQL 可以完全跳过前缀为“Tail User”的子目录。

对于实际工作中的绝大多数关联查询来说,事实表都不满足分区剪裁所需的前提条件。比如说,要么事实表不是分区表,要么事实表上没有过滤谓词,或者就是过滤谓词不包含分区键。

动态分区剪裁

DPP 指的是在数据关联的场景中,Spark SQL 利用维度表提供的过滤信息,减少事实表中数据的扫描量、降低 I/O 开销,从而提升执行性能。

在这里插入图片描述

首先,过滤条件 users.type = ‘Head User’会帮助维度表过滤一部分数据。维度表保留下来的 ID 值,仅仅是维度表 ID 全集的一个子集,如图中的步骤 1 所示。

然后,在关联关系 orders.userId = users.id 的作用下,过滤效果会通过 users 的 ID 字段传导到事实表的 userId 字段,也就是图中的步骤 2。满足关联关系的 userId 值,是事实表 userId 全集中的一个子集。

之后,把满足条件的 userId 作为过滤条件, 应用(Apply)到事实表的数据源,就可以做到减少数据扫描量,提升 I/O 效率,如图中的步骤 3 所示。

DPP 正是基于上述逻辑,把维度表中的过滤条件,通过关联关系传导到事实表,从而完成事实表的优化。

数据关联使用DPP需要满足三个额外的条件:

  • 事实表必须是分区表,而且分区字段(可以是多个)必须包含Join Key
  • DPP 仅支持等值 Joins
  • 维度表过滤之后的数据集要小于广播阈值

为什么需要满足 “维度表过滤之后的数据集要小于广播阈值” ?

实现 DPP 机制的关键在于,需要让处理事实表的计算分支,能够拿到满足过滤条件的 Join Key 列表,然后用这个列表来对事实表做分区剪裁。那么问题来了,用什么办法才能拿到这个列表呢?

Spark SQL 选择了一种“一箭双雕”的做法:使用广播变量封装过滤之后的维度表数据。 在维度表做完过滤之后,Spark SQL 在其上构建哈希表(Hash Table),这个哈希表的 Key 是用于关联的 Join Key。在我们的例子中,Key 是满足过滤 users.type = ‘Head User’条件的 users.id,Value是users.name。

哈希表构建完毕之后,Spark SQL 将其封装到广播变量中,这个广播变量的作用有二:

第 一个作用:给事实表用来做分区剪裁,哈希表中的 Key Set 用来给事实表过滤符合条件的数据分区;

第二个作用:参与后续的 Broadcast Join 数据关联,这里的哈希表,本质上就是 Hash Join 中的 Build Table,其中的 Key、Value,记录着数据关联中所需的所有字段,如 users.id、users.name,刚好拿来和事实表做 Broadcast Hash Join。

Spark SQL 选择了广播变量来有效利用 DPP 优化机制, 必须要谨慎设置spark.sql.autoBroadcastJoinThreshold

DPP的“硬伤”,Join Keys往往是高基数(cardinality)的字段,比如userId;而分区键往往要选择低基数的字段,否则数据的存储就会非常的分散。需要在存储效率和DPP之间做权衡,如果查询效率是第一优先级,那么我们其实还是可以强行对cardinality较高的Join Key做分区键。但如果相反,存储效率最大的concern,那么也就只好放弃取Join Key做分区键,放弃DPP优化机制。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DPP上位机的需求文档是对该软件工具的功能和性能要求进行详细描述和规定的文件。 首先,DPP上位机的需求文档应包括该软件工具的基本功能需求。这些功能包括但不限于数据采集、实时监测、图形显示、数据处理和报告生成等。此外,还需要明确支持的操作系统平台和硬件设备要求。 其次,需求文档应描述DPP上位机的用户界面需求。用户界面应设计简洁、易用,并具有直观的操作逻辑。用户能够通过界面完成各类配置、查询和操作,同时还应提供错误提示和帮助功能,以提高用户体验和操作效率。 另外,需求文档还应详细说明DPP上位机的性能需求。这包括对软件的响应时间、数据处理速度、数据精确度和并发性等指标的要求。同时也要考虑软件的可靠性和稳定性,以确保软件在运行过程中不容易出现崩溃、数据丢失或其他故障。 此外,需求文档还应考虑软件的可扩展性和可维护性。软件应具备模块化设计,便于后续功能扩展和维护。还应考虑软件的安全性需求,包括用户权限管理、数据加密、防止非法访问等。 最后,需求文档还应包含软件的测试要求和验收标准。软件在交付之前应经过充分的单元测试、集成测试和系统测试,以确保其功能正常、性能稳定。验收标准应明确软件交付后应满足的各项功能和性能指标,以及软件所涉及的文档和培训等配套工作。 综上所述,DPP上位机的需求文档应包括基本功能需求、用户界面需求、性能需求、扩展性需求、可维护性需求、安全性需求以及测试要求和验收标准等内容,以确保软件开发和交付的成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值