spark 3.3+ 之BloomFilter Runtime Filter

问题:

小表left join超大表,耗时要超1.5h,而且发生了FetchException导致任务多次重试之后挂掉的情况:

解决方案:

ai了一番之后,给出了一个靠谱的解决方案:Runtime BloomFilter:

复制代码
修改前:
...
from table_small_xxx
LEFT JOIN (
            select user_id
            from table_xxx
            where dt='${etl_date}'
    ) t3 ON (t1.user_id=t3.user_id)
    
修改后:

SET spark.sql.runtimeFilter.bloomFilter.enabled=true;    --  总开关。是否启用 Runtime BloomFilter
SET spark.sql.runtimeFilter.bloomFilter.applicationSideScanSizeThreshold=10GB;    -- application side (大表) 必须 ≥ 这个阈值, 才考虑加 BF
SET spark.sql.runtimeFilter.bloomFilter.creationSideThreshold=1GB;    -- creation side (小表) 必须 ≤ 这个阈值, 才会去构建 BF,避免bf太大
SET spark.sql.runtimeFilter.semiJoinReduction.enabled=true;    -- 另一种运行时过滤策略,适合build side很小无须使用bloomfliter直接用类似in的查询方式(其实也可以不加)

...
from table_small_xxx
LEFT JOIN (
    SELECT t.user_id
    FROM table_xxx t
    LEFT SEMI JOIN (
        SELECT DISTINCT user_id
        FROM table_small_xxx
        WHERE dt='${etl_date}'
      ) s ON (t.user_id = s.user_id)
      WHERE t.dt='${etl_date}'
) t3 ON (t1.user_id=t3.user_id)

原理介绍:

a left join b 时,a是小表,b是超大表。 那么就先对a中的join条件构造bloomfilter,broadcast到各个executor上,把超大表中的数据先剔除掉,这样就不会shuffle大量数据了。

复制代码
                   ┌────────────────────────────┐
                   │  Build Side (小的一边)       │
                   │  (creation side)            │
                   │  e.g. song_base_info 750万  │
                   └────────────┬────────────────┘
                                │ 1. 扫一遍, 把 join key 全部塞进 BF
                                ▼
                   ┌────────────────────────────┐
                   │     BloomFilter 数据结构     │
                   │  几 MB ~ 几十 MB 的 bitmap  │
                   └────────────┬────────────────┘
                                │ 2. 通过 Broadcast 分发到 tag 表 scan task
                                ▼
                   ┌────────────────────────────┐
                   │  Application Side (大的一边)│
                   │  e.g. tag 表 8862 亿行      │
                   │                             │
                   │  for each row in tag:        │
                   │    if BF.mightContain(key):  │
                   │      emit row  ← 1% 通过     │
                   │    else:                     │
                   │      skip      ← 99% 丢弃    │
                   └────────────┬────────────────┘
                                │ 3. 输出筛选后的小数据集
                                ▼
                       进入正常的 Join 阶段
相关推荐
SelectDB11 小时前
秒级弹性、最高降本 70%:SelectDB Serverless 如何重塑云数仓资源效率
大数据·后端·云原生
WhoAmI11 小时前
MapReduce框架原理解析一:InputFormat
大数据·hadoop
WhoAmI11 小时前
MapReduce框架原理解析三:OutputFormat
大数据·hadoop
WhoAmI11 小时前
MapReduce框架原理解析二:Shuffle
大数据·hadoop
大大大大晴天1 天前
Hudi技术内幕:Key Generation原理与实践
大数据
得物技术5 天前
从埋点需求到规则资产:Hermes Agent 重构得物数仓工作流
大数据·llm·ai编程
久美子5 天前
AI驱动数仓建设的Harness工程实践——本体建模、知识分层与上下文工程
大数据
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
大志哥1235 天前
ES和Logstash日志链路系统上线后遭遇切片爆炸(解决)
大数据·elasticsearch
果丁智能6 天前
物联网智能锁赋能集中式住宿:身份核验与远程权限管控的全链路技术实践
大数据·人工智能·物联网·智能家居