问题 | 拙见 | 解释 |
---|---|---|
什么时候使用DataFrame 的API
|
尽量少用 | 虽然写的时候很爽,当你回过头去看的时候,一团乱,不如一句sql 直观 |
什么时候使用UDF
|
优先考虑使用内置的UDF ,是在不行了再自己写 |
内置的UDF 大家都知道功能,你自己写的,别人还要看你的逻辑,容易误解 |
什么时候使用纯sql
|
尽可能多的使用 |
sql 是一种开发人员和分析人员都懂的语言,出于二者沟通成本低考虑,应优先考虑使用纯sql
|
1. SQL生成遇到的坑
最近工作中有一部分需要根据条件生成一些sql
语句来完成, 因为输入的参数可能会有成百上千个 (因为是一个最基础的功能,所以尽量把参数做到最细的粒度), 当只有几个参数的时候,生成的sql
可以欢快的跑起来, 但是测了一个3000多个参数的时候,在SparkSQL里连执行计划都做不出来, codegen
的时候直接64k
限制报错了, 查看了生成的sql
真是又臭又长, 里面有一大段重复的if-else
语句在里面, 这个语句会因为参数的增加而无限制增加, sql
类似如下:
select concat_ws(
'\u0001',
if(col='1', 'a', null),
if(col='2', 'b', null),
...
) as value
from table
where col in ('1', '2', ...) -- 出于效率考虑加的这个where语句使sql更大了
2. 解决方法
1. 将if-else
的逻辑封装到一个udf
这样在codegen
的时候可以避免这个问题, 同事提出的这个方法想了下,应该是可以的, 但是即便写一个udf
这相当于把if-else
挪到了一个函数里面去, 这个函数就得处理参数太多的问题, 想了一些办法,但因为一旦参数又增加, 比如到几百万这样的,一样会有问题
2. 做一个mapping
表出来
select mapping.value
from table
inner join mapping
on table.col = mapping.col
因为参数太多
- 我就想什么结构可以容纳很多的参数,想到了表 (这也可以看做一种数据结构)
- 然后再假定数据源存在一个表里了, 该怎么使用这个表
3. if-else
三阶段
- 单纯的
if-else
语句:if(col='1', 'a', null)
- 使用一个
map
:map_col[col_value]
- 使用一个
mapping
表: 类似本文这样一个例子
3. 一些建议
- 考虑更严重的情况 (参数更多)
- 更加抽象, 改变数据的形态 (单纯的一堆参数抽象出一张表)
- 试着限定一个更小的框, 只在
sql
里做, 只使用表结构