hive sql 怎么实现循环_Hive查询优化:

时间:2024-11-09 21:39:29

核心思想:是将hive程序当做mapreduce程序进行优化

我们知道大数据场景下,不怕数据量大,就怕数据倾斜,特别要慎用count(distinct),count(distinct)容易产生倾斜问题。

先来说说hive中sql语句转化为MapReduce的过程:

整个编译过程分为6个阶段:

定义Sql的语法规则,完成SQL词法,语法解析,将SQL转化为 抽象语法树AST Tree。

2.遍历抽象语法树AST Tree,抽象出查询的基本组成单元 QueryBlock查询块

3.遍历QueryBlock,翻译为执行操作树OperatorTree。

4.逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量。

5.遍历OperatorTree,翻译为MapReduce任务。

6.物理层优化器进行MapReduce任务的变换,生成最终的执行计划。

1.查看执行计划:

explain extended select count(*) from table;

可以查看整个sql的执行过程:

的运行方式

1.集群模式:需要先将本地程序打成Jar包,上传集群,如果执行出错,需要继续修改上传,在执行jar包,循环往复,影响开发效率。

2.本地模式:在hive中执行 set =true;

只能在测试和开发环境进行,并且限制输入文件的大小不能超过128M,如果大于该配置,仍会以集群方式运行。对于小数据执行时间可以明显被缩短。

没有开启本地模式:33.121秒

开启本地模式(3.578秒):

3.并行执行:

一次SQL计算中允许并行执行的job个数的最大值,Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。由于job包含多个阶段,而这些阶段并非完全互相依赖,所以可以启用并行执行,缩短整个job的执行时间(硬件资源充足,默认并行度是8)

设置参数:

4.严格模式(用于用户的某些查询操作):

hive通过设置以下参数模式开启严格执行模式:

set =strict;(默认情况:strict严格模式,nonstrict非严格模式)

查询限制:

1.对于分区表,必须添加where对于子句的查询,必须添加分区列,否则根本查询不了。

by语句必须包含limit输出限制,因为执行order by会将所有数据进行一次全排序,会将所有数据导入内存,执行排序,添加limit后会将数据打散分治计算,在mapper端和reducer端都会执行推测机制,避免了数据倾斜。

3.限制笛卡尔积的查询。

5.排序方式:

order by :对于查询结果做全排序,只允许有一个reduce处理 ,会造成数据倾斜, 一般不建议使用。严格模式下,必须结合limit来使用。

sort by :对于单个reduce的数据进行排序,分区内数据有序。

distribute by: 分区排序,分区间有序。经常和sort by结合使用

(distribute by column sort by column asc|desc的方式)

cluster by: sort by+distribute by,无法指定升序和降序规则。

Join

Map Join:在map端完成join(shuffle比较浪费时间,如果没有了reduce也就没有了shuffle)

两种实现方式:

1、SQL方式,在SQL语句中添加MapJoin标记(mapjoin hint)

手动:

SELECT /*+ MAPJOIN(smallTable) */ ,

FROM smallTable JOIN bigTable ON =

会优先将一张小表(默认小于25M,可以需要适当调节)的数据加载进内存中,然后大表的数据通过map端进行读取,然后和内存进行匹配,内存的计算速度很高,这样就在内存端进行了操作,不需要shuffle,不需要reduce

自动的mapjoin:

通过修改以下配置启用mapjoin:

set = true;(该参数为true时,Hive自动对左边的表统计量,如果是小表就加入内存,即对小表使用Map join)

相关配置参数:

;

(大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行)

手动和自动产生冲突,解决:

(默认值:true;是否忽略手动mapjoin hint 即mapjoin标记)

合并mapjoin

;

(默认值:true;将普通的join转化为普通的mapjoin时,是否将多个mapjoin转化为一个mapjoin)

;

(将多个mapjoin转化为一个mapjoin时,其表的最大值)

当三个表以上的表关联的时候,尽可能适用相同的连接键。会转化为一个mapreduce作业。

大表join大表(本质是reduce数据分布不均匀做成的数据倾斜)了解

空key过滤:有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。

空key转换:有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的reducer上。

7.map_side聚合

是否在map端执行combine

聚合比例:大于0.5不会聚合,反之发生聚合,预先会测试100000条数据

通过设置以下参数开启在Map端的聚合:

set =true;

相关配置参数:

map端group by执行聚合时处理的多少行数据(默认:100000)

进行聚合的最小比例(预先对100000条数据做聚合,若聚合之后的数据量/100000的值大于该配置0.5,则不会聚合)

map端聚合使用的内存的最大值

map端做聚合操作是hash表的最大可用内容,大于该值则会触发flush

是否对GroupBy产生的数据倾斜做优化,默认为false

将mapreduce变成两个MR,一个将数据进行均匀随机分布,第二个将指定的比例(0.5)往不同的reduce分发。虽然会慢一些,但是不会崩溃。注意(33%,66%,99%)

8.合并小文件

文件数目小,容易在文件存储端造成压力,给hdfs造成压力,影响效率.,将map和reduce的小文件进行合并,大于256M后不再参与合并

设置合并属性

是否合并map输出文件:=true

是否合并reduce输出文件:=true;

合并文件的大小:=256*1000*1000

9.去重统计

数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换

10.控制Hive中Map及Reduce的数量

Map数量相关的参数

一个split的最大值,即每个map处理文件的最大值

一个节点上split的最小值

一个机架上split的最小值

Reduce数量相关的参数

强制指定reduce任务的数量

每个reduce任务处理的数据量

每个任务最大的reduce数

重用

预先申请了一些资源,避免了重复对资源的重复申请和销毁工作

适用场景:

1.小文件数过多

个数过多

通过 set =n; 来设置

(n为task插槽个数)

缺点:设置开启之后,task插槽会一直占用资源,不论是否有task运行,直到所有的task即整个job全部执行完成时,才会释放所有的task插槽资源!