row_number数据倾斜的最佳解决方案
需求背景
来自京东外卖-数据研发二面
已知一张京东外卖骑手收入表 dws_jd_emp_salary_1d,存放各地区各骑手当日的外卖收入情况,计算各地区骑手当日收入前三的名单
BJ | 001 | 300 |
BJ | 002 | 100 |
BJ | 003 | 200 |
BJ | 004 | 150 |
BJ | 005 | 120 |
BJ | 006 | 500 |
BJ | 007 | 380 |
BJ | 008 | 300 |
SH | 009 | 600 |
SH | 010 | 360 |
SQL代码如下:
select area_id, emp_id, salary from ( select area_id, emp_id, salary, row_number() over(partition by area_id order by salary desc) rk from dws_jd_emp_salary_1d where dt = '20250523' ) t where rk <= 3
面试官继续问:真实场景中,这个代码运行的非常慢,如何优化?
问题分析
回答:如果真实场景运行的非常慢,那么我认为可能是由两种原因导致的
- 第一、员工收入表数据量非常大
- 第二、ROW_NUMBER按照area_id分组时发生了数据倾斜
综合来看,第一种原因的可能性并不是很大,外卖业务是一个新业务,同时数据源是一张天级别汇总表,数据量不会太大,那么我接下来主要说一下第二种情况如何解决
解决方案
-- 1、将同一个区域的员工分散到10个桶中分别进行排序,并且获取对应的前三名 with t1 as ( select area_id, emp_id, salary from ( select area_id, emp_id, salary, row_number() over(partition by area_id, round(rand()*10)order by salary desc) rk from dws_jd_emp_salary_1d where dt = '20250523' ) t where rk <= 3 ) -- 2、对同一个区域的员工再次进行排序,然后获取前三名即为所求 select area_id, emp_id, salary from ( select area_id, emp_id, salary, row_number() over(partition by area_id order by salary desc) rk from t1 ) t where rk <= 3
思考:为什么这样就可以提升代码运行效率?
#数据人的面试交流地##京东美团大战,你怎么看?#大数据开发面试笔记 文章被收录于专栏
包括大数据篇、计算机语言篇、计算机基础篇、算法刷题篇、面试经验篇等五大篇章: 大数据篇包括框架原理、源码解析、调优技巧、大数据场景题、项目实战、数仓理论等模块;计算机语言篇包括Java、Linux、大厂常考SQL面试题等模块;计算机基础篇包括计算机网络、操作系统、数据库、数据结构等模块;算法刷题篇包括大厂高频算法题、刷题速成计划等模块 面试经验篇包括BAT、美团、字节、快手、京东等大厂的面经合集