菜鸡的notebook(慢慢总结)

文章目录

一、hive组件

在这里插入图片描述
1、hive数据储存在hdfs上。
2、MapReduce,将SQL翻译为MapReduce任务。
3、metastore,元数据的储存。(默认存储在自带的derby 数据库中,推荐使用MySQL 存储Metastore)
表中有哪些字段,每个字段是哪些类型,表中有多少的数据量,在hdfs上有多少个文件,有多少行,有多大。这些都是元数据信息。
hive是将MySQL中的信息和hdfs中的信息做了一个双映射关系。当我们查询一张表的时候,先从MySQL中读取到这张表的元数据信息,然后根据元数据的指引,从hdfs上把数据找回。在这个过程中,如果使用到sum,count这种计算的函数,那么将会启用MapReduce任务。
上面3个,就是hive依赖的第三方组件。

在这里插入图片描述

1、client: 是客户端,提交一个SQL必然有客户端。连接客户端有两种方式。一种方式是Cli,普通的打开bin/hive,这样的方式;一种方式是JDBC,通过hiveserver2的方式,JDBC的方式连接,hive中提供一个beeline客户端,就是通过JDBC。
2、driver:连接客户端与服务端的桥梁。
3、真正的组件
1)解析器
将SQL解析成语法,判断语法是否正确,校验SQL,并不能真正的运行。
2)编译器
将抽象得到的语法 ,编译成执行任务,也就是operater tree操作树这样的内容。
3)优化器
对SQL进行优化,每一个优化的参数,都对应一个优化器。翻译成mr任务的时候会遍历所有的优化器(前提是开了这个属性)。
4)执行器
经过优化之后,任务被翻译成task tree。拿到任务树去执行。执行器会把任务树封装成一个mr任务当中,去做提交。

1(解析器).进入程序,利用Antlr框架定义HQL的语法规则,对HQL完成词法语法解析,将HQL转换为为AST(抽象语法树);遍历AST,对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。抽象出查询的基本组成单元QueryBlock(查询块),可以理解为最小的查询执行单元;  
2(编译器).遍历QueryBlock,将其转换为OperatorTree(操作树,也就是逻辑执行计划),可以理解为不可拆分的一个逻辑执行单元;
3(优化器).使用逻辑优化器对OperatorTree(操作树)进行逻辑优化。例如合并不必要的ReduceSinkOperator,减少Shuffle数据量;
4(执行器).遍历OperatorTree,转换为TaskTree。也就是翻译为MR任务的流程,将逻辑执行计划转换为物理执行计划;使用物理优化器对TaskTree进行物理优化(mapjoin等优化)6.生成最终的执行计划,提交任务到Hadoop集群运行。

SQL执行顺序
1、FROM:这个只需要说一点的是JOIN这一步包含在FROM里面,总之就是先确定表,加载所有表的所有行。(from相当于是加载了这张表,执行顺序在select之前的,都可以选择任意一个字段,因为是整张表的加载。)
2、WHERE:过滤掉不需要的行
3、GROUP BY:根据表达式或者列名来聚合(分组),分组完成后,所有的列只剩下了作为组名的列,组内部只对聚合函数可见。
4、聚合函数:聚合函数相当于可以进入分组的内部,然后计算出一个只有一个值的结果,例如组内的最大最小平均总和。(聚合函数是对一列的聚合)
5、HAVING:过滤掉—聚合后—的不需要的行
6、窗口函数:在此时的所有行开窗口,并在窗口内执行窗口函数
7、SELECT:选择需要的列,也叫project,投射
8、DISTINCT:在选择的列里面进行(xing)行(hang)去重
9、UNION,INTERSECT,EXCEPT:对得到的结果进行集合操作
10、ORDEY BY:对进行完集合操作后得到的结果集排序
11、OFFECT:没见过,不知道是干嘛的,别人说“Don’t use offset”
12、LIMIT,FETCH,TOP:最后选择前几行作为最终的结果

二、hive优化

1、谓词下推(默认开启)
谓词,是指用来描述或判断客体性质、特征或客体之间关系的词项。在SQL中即返回值为布尔值的函数。
   谓词下推,在Hive中叫Predicate Pushdown,含义是指在不影响结果的前提下,尽量将过滤条件提前执行,使得最后参与join的表的数据量更小。谓词下推后,过滤条件将在map端提前执行,减少map端输出,降低了数据传输IO,节约资源,提升性能。
Hive中通过配置hive.optimize.ppd参数为true,开启谓词下推,默认就是true开启状态。
1)表的分类
1.  Preserved Row table:保留表

        a left (outer) join b      中的 a 表;

        a right (outer) join b    中的 b 表;

        a full outer join b         a 和 b 表都是 保留表。

2.  Null Supplying table:提供null值的表,也就是 非保留表,在join中如果不能匹配上的使用null填充的表。

        a left (outer) join b     中的 b 表; 

        a right (outer) join b   中的 a 表,

        a full outer join b        a 和 b 表都是 null值保留表

3.  During Join predicate:join中谓词,就是on后面的条件。

        R1 join R2 on R1.x = 5   --> R1.x = 5就是join中谓词

4.  After Join predicate:join后谓词,就是where后面的条件。

        a left join b where a.t=1  --> a.t=1 就是join后谓词
2)Left outer Join & Right outer Join
!!!测试时,关闭 cbo 优化:set hive.cbo.enable=false

案例一:过滤条件写在 where, 且是 保留表的字段    

explain

select o.id from bigtable b

left join bigtable o 

where b.id <= 10;

 --> 可以谓词下推(能在 map 阶段提前过滤)



案例二:过滤条件写在 where, 且是 非保留表的字段   

explain

select b.id,o.id from bigtable b

left join bigtable o

where o.id <= 10;

--> 不可以谓词下推(能在 map 阶段提前过滤)



案例三:过滤条件写在 on, 且是 保留表的字段        

explain

select o.id from bigtable b

left join bigtable o

on b.id <= 10;

--> 不可以谓词下推(不能在 map 阶段提前过滤)



案例四:过滤条件写在 on, 且是 非保留表的字段      

explain

select o.id from bigtable b

left join bigtable o

on o.id <= 10;

--> 可以谓词下推(能在 map 阶段提前过滤)

=总结=

在关闭cbo的情况下:
在这里插入图片描述
默认的情况下,是开启的,也就是true,只有 保留字段(left的左表) - on 这个是不可以的。因为作为主表,在关联的时候要保证数据的完整性。

!!!注意:

1、对于 Left outer Join ,右侧的表写在 on后面、左侧的表写在 where后面,性能上有提高;

2、对于 Right outer Join,左侧的表写在 on后面、右侧的表写在 where后面,性能上有提高;

3)Full outer Join
案例一:过滤条件写在 where, 且是 保留表的字段     

explain

select o.id from bigtable b

full join bigtable o 

where b.id <= 10;

--> 可以谓词下推(能在 map 阶段提前过滤)

案例二:过滤条件写在 where, 且是 非保留表的字段   

explain

select b.id,o.id from bigtable b

full join bigtable o

where o.id <= 10;

--> 可以谓词下推(能在 map 阶段提前过滤)

案例三:过滤条件写在 on, 且是 保留表的字段        

explain

select o.id from bigtable b

full join bigtable o

on b.id <= 10;

--> 不可以谓词下推(不能在 map 阶段提前过滤)

案例四:过滤条件写在 on, 且是 非保留表的字段      

explain

select o.id from bigtable b

full join bigtable o

on o.id <= 10;

--> 不可以谓词下推(不能在 map 阶段提前过滤)

=总结=

1. 如果不开启 cbo,写在 on后面,还是 where后面,都不会谓词下推

2. 默认的话,是开启了 cbo,写在 where 可以 谓词下推, 写在 on 不可以 谓词下推。因为要保证关联的时候数据的完整性,on后面不能谓词下推。

-- 也就是说,full join的时候,只有开启cbo的时候,where后面可以谓词下推。
4)inner Join
Inner Join 不管有没有开启cbo,不管写在 on后面 还是 where后面,都会进行谓词下推。
2、MapJoin(默认开启)
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理
开启MapJoin参数设置

设置自动选择Mapjoin( 默认为true):set hive.auto.convert.join = true;

大表小表的阈值设置(默认25M一下认为是小表):set hive.mapjoin.smalltable.filesize=25000000;
3、行列过滤
1) 列处理
 select 后面选择需要的列,少用select   *
2) 行处理
表之间关联的时候,将副表的过滤之后再进行join,这样的话,直接关联的数据就会少很多。如果在关联之后进行where过滤的话,这样的话费时间了。
也就是
  table1 a
         left join
  (select  *
   from table2 b1 
   where b1.xxx = xxx
  )b
也就是过滤完再关联,比关联之后再过滤效率高。
也就是类似与谓词下推,where的那种情况。
4、采用列式储存
5、创建分区表
  查询指定分区,减少查询的数据量,加快查询的速度。
6、优化小文件
1) 小文件是如何产生的
1、动态分区插入数据,产生大量的小文件,从而导致map的数量剧增。
2、reduce数量越多,小文件也就越多(reduce的个数和输出文件是对应的)
3、数据源本身就有大量的小文件。
2) 解决方案
1、执行map之前合并小文件,combinehiveinputformat具有对小文件进行合并的功能。
 set hive.input.format=org.apache.hadoop.hive.al.io.CombineHiveInputFormat
 也就是设置hive的输入格式,CombineHiveInputFormat(合并hive输入格式化,中文记忆法)
2、merge合并
 1)只有map任务,也就是map-only,任务结束的时候合并小文件。
 set hive.merge.mapfiles =  true ,这个默认就是true2)有map任务,也有reduce任务。是在mapreduce任务结束之后,进行合并小文件。
 set hive.merge.mapreducefiles =  true ,这个默认是false,需要手动设置为true3)小文件合并的时候,默认的话是最后合并成一个256M的文件。
 set hive.merge.size.per.task = 268435456
 4)我们设置一个阀值为16m,当输出的文件的平均大小小于这个阀值得时候,启动一个独立的map-reduce任务进行merge。
 set hive.merge.smallfiles.avgsize = 16777216
3、开启JVM重用
7、处理数据倾斜
1) 定义
大量的相同key被partition分配到一个分区,处理的数据量太大。
2) 现象
当我们看任务进度长时间维持在99%(或100%),查看  任务监控 页面 就会发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大,这就是数据倾斜的直接表现。
3) 原因以及解决
1、key分布不均匀,会导致大量的数据到了一个分区中,也就是进入一个reducer中,导致计算量过大,发生数据倾斜。(适用于聚合类操作,求sum,count这种)
解决:开启数据倾斜时候的负载均衡,进行两次MapReduce计算。
    set hive.groupby.skewindata = true
--第一次MapReduce的时候, 会给key打上随机数,随机分配到某个reducer中进行计算。
--第二次MapReduce的时候,key中的随机数去掉了,然后key分配到对应的reducer中,进行计算。
2、两张表关联的时候,关联的字段类型不一致。
解决:其中一个类型进行强转成和另一个一致的。
3、采用sum() group by的方式来替换count(distinct)完成计算。
4、表中的null值,会进入同一个reduce中,需要打散
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值