Spark SQL之SQL优化
主要关注于执行性能问题
1、避免使用不必要的UDF函数
UDF:用户定义函数,可以直接在SQL语句中计算的函数,如:count、sum、avg、max、min等
2、没有指定数据分区
SQL-1: SELECT date FROM test_table WHERE date = '20170829' and value = 1;
SQL-2: SELECT date FROM test_table PARTITION(p_20170829) p WHERE value = 1
SQL-1虽然通过where表达式能够筛选到并执行所需的分区,但是在分析的时候会先获取所有的分区列表再进行筛选,会导致更多的内存占用,显然SQL-2更优
3、避免使用笛卡尔积
简单了解什么是sql里的笛卡尔积
SQL-1: select * from gbk, utf8 where gbk.key= utf8.key
SQL-2: select * from gbk join utf8 where gbk.key= utf8.key
上面是先对tabel进行笛卡尔积再where筛选,应当按如下方式书写
select * from gbk join utf8 on gbk.key= utf8.key
4、show Rowcount
读取一个表有多少行记录,虽然count也可以,但是速度非常慢!
show rowcount extended test;
按分区来显示每个分区有多少行记录
5、show Tablesize
读取一个表有多大,单位是字节
show tablesize extended test;
6、避免使用delete和update
7、当存在小表join的时候,查看是否可以使用mapjoin
MAPJION会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多。
简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join。这样就不会由于数据倾斜导致某个reduce上落数据太多而失败。
8、数据倾斜
Join的时候,相同的key会hash到同一task中进行。如果某个key值太多,这个task就会成为瓶颈。
简单来说就是大量的相同key被partition分配到一个分区里,造成了’一个人累死,其他人闲死’的情况,这种情况是我们不能接受的,这也违背了并行计算的初衷,首先一个节点要承受着巨大的压力,而其他节点计算完毕后要一直等待这个忙碌的节点,也拖累了整体的计算时间,可以说效率是十分低下的.
判断数据倾斜的方法:
select id,count(id) as id_nums group by id order by num desc
处理数据倾斜的方法
数据分离:
select * from (
select * from A1 join B on A1.id = B.id
union all
select /*+ MAPJOIN (A2) */ * from A2 join B on A2.id = B.id
)
数据打散:
处理之前需要先查看一下id的分布情况
表A:
SELECT id, value, concat(id, string1(cast(rand() * 10000 as int)%3)) as new_id
FROM A;
表B:
SELECT id, value, concat(id, suffix) as new_id
FROM (
SELECT id, value, suffix
FROM B Lateral View explode(array(0,1,2)) tmp as suffix
)
9、join与groupby的顺序
如果Join 后有聚合函数操作,尽可能把聚合操作放到Join 之前,这样在Join 时 key 是单一的,避免数据倾斜。例如,
select t1.key, t1.total from
(select key ,sum(value) as total from t1 group by key
) t1
join t2 on t1.key = t2.key
前提是t2的key没有重复