hive_sql简单优化方案

这里的优化方面只在sql【spark】层面,对于参数的调整,这里不做介绍。

1、表设计层面优化

① 尽量使用分区表操作。
② 利用桶表优化
③ 选择合适的文件存储格式

2、语法和参数层面

① 优先过滤数据

尽量减少每个阶段的数据量,对于分区表能用上分区字段的尽量使用,同时只选择后面需要使用到的列,最大限度的减少参与join的数据量。
除了需要必须表里所有的字段,否则禁止使用select *

② 小表join大表原则

小表join大表的时候应遵守小表join大表原则,原因是join操作的reduce阶段,位于join左边的表内容会被优先加载进内存,将条目少的表放在左边,可以有效减少发生内存溢出的几率,join中执行顺序是从左到右生成job,应该保证连续插叙中的表的大小从做到右依次增加。

③尽量原则操作

尽量避免一个sql包含复杂的逻辑,可以使用中间表来完成复杂的逻辑。

④ order by 优化

order by只能在一个reduce进程中进行,所以如果对一个大数据集进行order by,会导致一个reduce进程中处理的数据相当大,造成查询执行缓慢。
推荐:在最终结果上进行 order by ,不要在中间的大数据集上进行排序。如果最终结 果较少,可以在一个reduce上进行排序时,那么就在最后的结果集上进行 order by。
如果是去排序后的前N条数据,可以使用 distribute by 和 sort by 在各个 reduce上进行排序后前N条,然后再对各个reduce的结果集合合并后在一个 reduce中全局排序,再取前N条,因为参与全局排序的 order by 的数据量最多 是 reduce个数 * N ,所以执行效率很高。

⑤ count distinct优化

‐‐ 优化前(只有一个reduce,先去重再count负担比较大): 
select count(distinct id) from tablename;
‐‐ 优化后(启动两个job,一个job负责子查询(可以有多个reduce),另一个job负责 count(1)):
select count(1) from (select distinct id from tablename) tmp;

⑥ 推荐使用谓词下推

如逻辑允许,尽量使用join的方式,不要使用left join【外连接会导致谓词下推失效】,
以下两种方式会让谓词下推生效
1、

select a.id,a.value1,b.value2 from table1 a
join (select b.value2,b.id from table2 b where b.dt>='2018-12-01' and b.dt<'2019-01-01') c
on (a.id=b.id)

2、

select a.id,a.value1,b.value2 from table1 a
join table2 b on a.id=b.id
where b.dt>='2018-12-01' and b.dt<'2019-01-01'

但相对来说,更推荐第一种方式,存在优先过滤数据,并使谓词下推生效。

谓词下推:

Hive谓词下推(Predicate pushdown)
关系型数据库借鉴而来,关系型数据中谓词下推到外部数据库用以减少数据传输
基本思想:尽可能早的处理表达式
属于逻辑优化,优化器将谓词过滤下推到数据源,使物理执行跳过无关数据
参数打开设置:hive.optimize.ppd=true

⑦ 关于数据倾斜

我们在join的过程中经常会出现数据倾斜的情况发生,例如null值数据过多,全部聚集到一端运行,会严重影响效率,所以这里针对sql:
建议如果出现数据倾斜,可选择hash方式将数据打散。

select id,merchant_id from trade_order distribute by id % 100

⑧ 如果union all的部分个数大于2,或者每个union部分数据量大,应该拆成多个insert into 语句

实际测试过程中,执行时间能提升50%

⑨ 对于在一个查询中多次使用到一张表

建议使用 with table_name as ,原因:with会将这张表提前缓存到内存中,防止多次读取,全表扫描操作。

你可能感兴趣的:(spark)