面试加分秘籍:校招数据倾斜场景下的SQL优化方案

校招面试经常会问大家有没有过调优的经验,相信大家的回答基本都是往数据倾斜和小文件问题这两方面回答,对于数据倾斜相信大部分同学对热key打散或null值引发的倾斜已经非常熟悉,但这些内容面试官也是听腻了,希望大家在面试时候讲一些高大尚的案例,在描述的时候一定要有背景,有解决方案,最后结果,毕竟数据倾斜不会无故产生,一定是有业务背景的,这里给大家分享一种数据倾斜优化案例。

1.Uid和oaid之间的转化

在用增的拉新拉回业务中,经常会用到oaid来识别具体的设备是不是公司用户,所以我们需要将uid→oaid,需求目的:找到当日拉新的uid对应的oaid映射关系

代码如下:

  • 1.从id mapping表中找出uid→oaid的映射关系;

  • 2.根据最后一次活跃时间对uid→oaid映射关系去重;

  • 3.将算法提供的uid人群圈选出对应的oaid。

原来的sql

复制代码
select
  t1.user_id,
  oaid_md5
from
  (
    select
      L.uid user_id,
      md5(L.oaid) oaid_md5
    from
      (
        select
          distinct uid,
          oaid
        from
          (
            select
              uid,
              oaid,
              row_number() over (
                partition by oaid
                order by
                  cast(last_active_timestamp as bigint) desc
              ) as rn
            from
              idmapping as G
            where
              G.p_date = '20250324'
              and G.left_type = 'USER_ID'
              and G.right_type = 'OAID'
          ) tt
        where
          tt.rn = 1
      ) as L
      left join (
        select
          id
        from
          zuobishebei -- 作弊设备
        where
          p_date = '{{ds_nodash}}'
          and supplier = 'cheat'
      ) as P on (md5(L.oaid) = P.id)
    where
      P.id is null
  ) t2
  join (
    SELECT
      user_id
    FROM
      list_ground_truth
    WHERE
      p_date = '20250324'
  ) t1 on t1.user_id = t2.user_id

粗略一看,符合正常计算流程和顺序,但这段sql出现了明显的数据倾斜。

经过排查代码中有两块可能引起倾斜,一个是join,一个row number,先查询一下uid→oaid映射情况,发现部分的uid映射过10亿多的oaid,导致在去重的时候发生了数据倾斜。

解决方案

  • 1.使用过滤条件和分组操作减少数据量;

  • 2.通过调整连接顺序和提前应用过滤条件,减少了中间数据量;

  • 3.如果倾斜仍然存在,考虑对倾斜字段进行分区或使用 broadcast join 来进一步优化。

优化后:

复制代码
SELECT
  user_id,
  md5(paid) AS oaid
FROM
  (
    SELECT
      user_id,
      paid,
      ROW_NUMBER() OVER (
        PARTITION BY user_id
        ORDER BY
          CAST(last_active_timestamp AS BIGINT) DESC
      ) AS rn
    FROM
      (
        SELECT
          t1.user_id,
          t2.paid,
          t2.last_active_timestamp
        FROM
          (
            SELECT
              user_id
            FROM
              list_ground_truth
            WHERE
              p_date = '20250324'
          ) t1
          JOIN (
            SELECT
              uid,
              oaid,
              G.last_active_timestamp
            FROM
              idmappingG
            WHERE
              G.p_date = '20250324'
              AND G.left_type = 'USER_ID'
              AND G.right_type = ' OAID '
            GROUP BY
              G.left_value,
              G.right_value,
              G.last_active_timestamp
          ) t2 ON t1.user_id = t2.uid
      ) t3
  ) t1
WHERE
  rn = 1

原始脚本和优化后的脚本在逻辑上保持一致,但重点在于先jion较小的表(idmapping和 list_ground_truth),在进行row number,这样可以在join时先走map join同时减少row number执行的数据量。

相关推荐
坤小满学Java20 分钟前
【郑州轻工业大学|数据库】数据库课设-酒店管理系统
数据库·mysql·课程设计
DQI-king37 分钟前
ZYNQ学习记录FPGA(五)高频信号中的亚稳态问题
数据库
Yrrr12 小时前
Redis 持久化机制详解:RDB、AOF 原理与面试最佳实践(AOF篇)
数据库·redis·面试·职场和发展
知月玄2 小时前
网页后端开发(基础5--JDBC VS Mybatis)
数据库·mysql
怪只怪满眼尽是人间烟火2 小时前
SQL分片工具类
网络·数据库·sql
国际云2 小时前
腾讯云搭建web服务器的方法
服务器·数据库·云计算·区块链
袋鼠云数栈3 小时前
AI Infra 运维实践:DeepSeek 部署运维中的软硬结合
大数据·运维·数据库·数据中台·数栈
云和恩墨4 小时前
国网某省电力借zDBM重构数据库容灾防线,400TB核心资产迈入分布式实时保护时代
数据库·分布式·重构
大千AI助手4 小时前
ER图:数据库设计的可视化语言 - 搞懂数据关系的基石
数据库
李强57627825 小时前
语法制导的语义计算(包含python源码)
java·数据库·python