当前位置: 首页 > news >正文

spark-Join Key 的基数/rand函数

在数据处理中,Join Key 的基数 是指 Join Key 的唯一值的数量(也称为 Distinct Key Count)。它表示某个字段(即 Join Key)在数据集中有多少个不同的值。

1. Join Key 基数的意义

  • 高基数:Join Key 的唯一值数量较多,例如用户 ID、订单号等字段,每个值通常是唯一的。
  • 低基数:Join Key 的唯一值数量较少,例如性别(只有 “男” 和 “女” 两种值)、国家(通常只有几十到几百个值)。

Join Key 的基数直接影响 Join 操作的性能和数据分布,尤其是在分布式计算框架(如 Spark)中,基数的大小会影响数据的分区和 Shuffle 的效率。

2. Join Key 基数的计算

假设有一个数据表 orders,包含以下字段:

order_id | user_id | country1     |   101   |   US2     |   102   |   US3     |   103   |   UK4     |   101   |   US5     |   104   |   CA
计算基数的步骤
  1. 选择 Join Key 字段:假设我们选择 user_id 作为 Join Key。
  2. 统计唯一值数量
    • user_id 的唯一值为 {101, 102, 103, 104}
    • 基数为 4(即有 4 个不同的用户 ID)。

3. Join Key 基数对 Join 的影响

3.1 高基数的 Join Key
  • 定义:Join Key 的唯一值数量较多,接近数据集的总行数。例如订单号、用户 ID 等。
  • 特点
    • 数据分布通常较均匀,因为每个分区中 Join Key 的值都可能不同。
    • Shuffle 的数据量较大,但不会出现数据倾斜问题。
  • 适用 Join 类型
    • Sort-Merge Join:更适合高基数的 Join Key,因为数据分布均匀,排序和合并效率较高。
    • Broadcast Join:如果其中一个数据集较小,也可以使用广播机制避免 Shuffle。
3.2 低基数的 Join Key
  • 定义:Join Key 的唯一值数量较少,远小于数据集的总行数。例如性别(只有 “男” 和 “女” 两种值)。
  • 特点
    • 数据分布容易不均匀(数据倾斜),因为某些分区可能包含大量相同的 Join Key。
    • Shuffle 的数据量可能较小,但由于数据倾斜,某些分区的计算时间会显著增加。
  • 适用 Join 类型
    • Broadcast Join:如果其中一个数据集较小,广播机制可以避免数据倾斜。
    • Shuffle Hash Join:适合低基数的 Join Key,但需要注意数据倾斜问题。

4. Join Key 基数的实际应用场景

场景 1:高基数 Join Key
  • 示例
    • 表 A:user_id(100 万行,100 万个唯一值)。
    • 表 B:user_id(10 万行,10 万个唯一值)。
  • 分析
    • user_id 是高基数字段,数据分布均匀。
    • Spark 可以选择 Sort-Merge JoinBroadcast Join(如果表 B 较小)。
场景 2:低基数 Join Key
  • 示例
    • 表 A:country(100 万行,只有 3 个唯一值:US、UK、CA)。
    • 表 B:country(10 万行,只有 3 个唯一值:US、UK、CA)。
  • 分析
    • country 是低基数字段,数据分布可能不均匀(例如 US 的数据量远大于 UK 和 CA)。
    • Spark 可能选择 Shuffle Hash Join,但需要解决数据倾斜问题。

5. 如何优化基数对 Join 的影响

5.1 高基数 Join Key
  • 优化策略
    • 如果数据量较大且 Join Key 基数高,确保数据分区均匀,避免分区过多或过少。
    • 如果其中一个数据集较小,可以使用 Broadcast Join 避免 Shuffle。
5.2 低基数 Join Key
  • 优化策略
    1. 处理数据倾斜
      • 使用随机前缀对 Join Key 进行打散:
        val df1 = df1.withColumn("key", concat(col("country"), lit("_"), rand()))
        
- `RAND()`- 生成一个介于 `[0, 1)` 的随机浮点数。- 每行都会生成一个新的随机数。
- `FLOOR(RAND() * 10)`- 将随机数放大到 `[0, 10)` 的范围,并取整,生成一个随机整数(09)。- 这个整数作为随机前缀的一部分。
SELECT *,CONCAT(country, '_', CAST(FLOOR(RAND() * 10) AS STRING)) AS key
FROM df1
 - 在 Join 后去除随机前缀,恢复原始数据。
  1. 使用 Broadcast Join
    • 如果其中一个数据集较小,可以广播小表,避免 Shuffle 和数据倾斜。
  2. 分区优化
    • 调整分区数,使得每个分区的数据量尽量均匀。

6. 总结

Join Key 基数定义特点适用 Join 类型优化策略
高基数唯一值数量较多,接近总行数数据分布均匀,Shuffle 数据量大,但不会出现数据倾斜Sort-Merge Join、Broadcast Join确保分区均匀,使用 Broadcast Join(如果小表较小)。
低基数唯一值数量较少,远小于总行数数据分布不均匀,容易出现数据倾斜Shuffle Hash Join、Broadcast Join处理数据倾斜(随机前缀打散、分区优化),使用 Broadcast Join(如果小表较小)。

7. 实际案例*

案例 1:用户订单分析
  • 场景:将用户表(user_id)与订单表(user_id)进行 Join。
  • 分析
    • user_id 是高基数字段,数据分布均匀。
    • 如果用户表较小,可以使用 Broadcast Join
    • 如果用户表较大,使用 Sort-Merge Join
案例 2:国家销售额分析
  • 场景:将销售表(country)与国家表(country)进行 Join。
  • 分析
    • country 是低基数字段,数据分布可能不均匀(如 US 数据量远大于其他国家)。
    • 可能出现数据倾斜问题,需要通过随机前缀或 Broadcast Join 优化。

6、 RAND() 生成随机数的原理

1.1 RAND() 的工作机制
  • 定义:RAND() 是 SQL 中用于生成随机数的函数,返回一个介于 [0, 1) 的浮点数
  • 随机数生成原理:
    • RAND() 使用伪随机数生成器(PRNG,Pseudo-Random Number Generator),基于一定的算法和种子(Seed)生成随机数。
    • 如果不指定种子,RAND() 每次调用都会基于系统当前状态(如时间戳)生成一个新的随机数。
    • 如果指定种子(如 RAND(seed)),则每次调用会生成相同的随机数序列。
1.2 RAND() 在多个表中的表现
  • 无种子情况下
    • 每次调用 RAND() 都会生成一个新的随机数
    • 在不同表中调用 RAND() 时,生成的随机数通常不同,因为它们基于各自的计算环境(如时间戳)。
  • 指定种子情况下
    • 如果在多个表中使用相同的种子(如 RAND(42)),则生成的随机数序列会相同
    • 这种情况下,可以确保不同表中的随机数一致。

2. 生成随机数不一致,导致关联不上解决方案

2.1 使用固定种子
  • 原理
    • 在多个表中使用相同的种子(如 RAND(42)),确保随机数生成逻辑一致。
    • 这样可以保证 country 的随机前缀在两个表中一致。
  • 实现
    SELECT CONCAT(country, '_', CAST(FLOOR(RAND(42) * 10) AS STRING)) AS key
    FROM tableA;SELECT CONCAT(country, '_', CAST(FLOOR(RAND(42) * 10) AS STRING)) AS key
    FROM tableB;
    
  • 效果
    • 表 A 和表 B 中的 country 值生成的随机前缀一致(如 US_7),确保 Join Key 匹配。
2.2 使用哈希函数
  • 原理
    • 使用哈希函数(如 MD5SHA)对 country 进行处理,生成一个固定的随机前缀。
    • 哈希函数的结果是确定性的,同样的输入会生成相同的输出。
  • 实现
    SELECT CONCAT(country, '_', CAST(FLOOR(ABS(HASH(country)) % 10) AS STRING)) AS key
    FROM tableA;SELECT CONCAT(country, '_', CAST(FLOOR(ABS(HASH(country)) % 10) AS STRING)) AS key
    FROM tableB;
    
  • 效果
    • 表 A 和表 B 中的 country 值生成的哈希前缀一致(如 US_7),确保 Join Key 匹配。
3.3 使用分组 ID 或预处理
  • 原理
    • 在数据预处理阶段,为每个 country 分配一个固定的分组 ID(如 US -> 0UK -> 1),然后在 Join Key 中使用分组 ID。
  • 实现
    • 在数据预处理阶段:
      SELECT country,ROW_NUMBER() OVER (ORDER BY country) AS group_id
      FROM tableA;
      
    • 在 Join Key 中使用 group_id
      SELECT CONCAT(country, '_', group_id) AS key
      FROM tableA;SELECT CONCAT(country, '_', group_id) AS key
      FROM tableB;
      
  • 效果
    • 表 A 和表 B 中的 country 值生成的分组 ID 一致,确保 Join Key 匹配。
3.4 扩大随机数范围
  • 原理
    • 增加随机数的范围(如 RAND() * 100),减少随机前缀重复的概率。
    • 虽然不能完全解决随机数不一致的问题,但可以缓解数据倾斜问题。
  • 实现
    SELECT CONCAT(country, '_', CAST(FLOOR(RAND() * 100) AS STRING)) AS key
    FROM tableA;SELECT CONCAT(country, '_', CAST(FLOOR(RAND() * 100) AS STRING)) AS key
    FROM tableB;
    

4. 推荐方案

4.1 如果需要随机前缀一致性
  • 使用固定种子(如 RAND(42))或哈希函数(如 HASH(country))生成随机前缀,确保 Join Key 在多个表中一致。
4.2 如果需要减少数据倾斜
  • 扩大随机数范围(如 RAND() * 100),减少随机前缀重复的概率。
  • 或者在数据预处理阶段对 Join Key 进行分组。

5. 总结

方法是否解决随机前缀一致性问题是否解决数据倾斜问题适用场景
固定种子(RAND(seed))确保多个表的 Join Key 一致。
哈希函数(HASH)部分解决确保一致性,同时减少倾斜。
分组 ID需要预处理,适合复杂场景。
扩大随机数范围部分解决适合倾斜问题较轻的场景。

相关文章:

  • 海纳思(Hi3798MV300)机顶盒遇到海思摄像头
  • RT-Thread 深入系列 Part 5:物联网与网络应用实战
  • 51c视觉~合集37
  • 使用FastAPI微服务在AWS EKS上实现AI会话历史的管理
  • 计算机网络 4-2-2 网络层(IPv4)
  • 解锁 DevOps 新境界 :使用 Flux 进行 GitOps 现场演示 – 自动化您的 Kubernetes 部署
  • 【RT-Thread Studio】nor flash配置Fal分区
  • Windows:Powershell的使用
  • 程序代码篇---esp32视频流处理
  • Taro 编译不平不同平台小程序
  • 《类和对象(中)》
  • 分布式事务快速入门
  • Ubuntu 与 Windows 双系统环境下 NTFS 分区挂载教程
  • Autoware message_filters::Synchronizer链接错误问题
  • 如何删除网上下载的资源后面的文字
  • 数字孪生实战笔记(1)数字孪生的含义、应用及技术体系
  • zdir3个人网盘dockerfile打包
  • 深入解析:如何基于开源p-net快速开发Profinet从站服务
  • C# WinForm DataGridView 非常频繁地更新或重新绘制慢问题及解决
  • WPF 性能 UI 虚拟化 软件开发人员的思考
  • ​中国超大规模市场是信心所在——海南自贸港建设一线观察
  • 海航回应“男团粉丝为追星堵住机舱通道”:已紧急阻止
  • 黑灰产工作室为境外诈骗集团养号引流,冒充美女与男性裸聊后敲诈勒索
  • 谜语的强制力:弗洛伊德与俄狄浦斯
  • 加力、攻坚、借力、问效,上海为优化营商环境推出增量举措
  • 非洲中青年军官代表团访华,赴北京、长沙、韶山等地参访交流