大数据面试系列之——Hive

Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据

1.Hive与传统数据库的区别
1、数据存储位置:Hive是建立在Hadoop之上的,所有的Hive的数据都是存储在HDFS中的。而数据库则可以将数据保存在块设备或本地文件系统中。
2、数据格式:Hive中没有定义专门的数据格式,由用户指定,需要指定三个属性:列分隔符,行分隔符,以及读取文件数据的方法。数据库中,存储引擎定义了自己的数据格式。所有数据都会按照一定的组织存储。
3、数据更新:Hive的内容是读多写少的,因此,不支持对数据的改写和删除,数据都在加载的时候中确定好的。数据库中的数据通常是需要经常进行修改。
4、执行延迟:Hive在查询数据的时候,需要扫描整个表(或分区),因此延迟较高,只有在处理大数据是才有优势。数据库在处理小数据是执行延迟较低。
5、索引:Hive没有,数据库有
6、执行:Hive是MapReduce,数据库是Executor
7、可扩展性:Hive高,数据库低
8、数据规模:Hive大,数据库小

2.Hive的内部表和外部表的区别
在删除内部表的时候,Hive将会把属于表的元数据和数据全部删掉,而删除外部表的时候,Hive仅仅删除外部表的元数据,数据是不会删除的。

3.Hive的分区表和分桶表的区别
分区:
Hive的分区使用HDFS的子目录功能实现。每一个子目录包含了分区对应的列名和每一列的值
Hive的分区方式:由于Hive实际是存储在HDFS上的抽象,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。
分桶:
分桶表是在表或者分区表的基础上,进一步对表进行组织,Hive使用 对分桶所用的值;
进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。

主要区别有三:
1.分区表对应的是HDFS上的目录,分桶表对应的是HDFS上的文件。
2.分桶随机分割数据库,分区是非随机分割数据库。因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。
3.分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度);桶是更为细粒度的数据范围划分,分桶的比分区获得更高的查询处理效率,使取样更高效。

4.Hive表的元数据存储方式
Hive支持三种不同的元存储服务器,分别为:内嵌式元存储服务器、本地元存储服务器、远程元存储服务器,每种存储方式使用不同的配置参数。
1.内嵌式元存储主要用于单元测试,在该模式下每次只有一个进程可以连接到元存储,Derby是内嵌式元存储的默认数据库。
2.在本地模式下,每个Hive客户端都会打开到数据存储的连接并在该连接上请求SQL查询。
3.在远程模式下,所有的Hive客户端都将打开一个到元数据服务器的连接,该服务器依次查询元数据,元数据服务器和客户端之间使用Thrift协议通信。

5.Hive中order by,sort by, distribute by ,cluster by的区别
1.order by : order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序),然而只有一个Reducer,会导致当输入规模较大时,消耗较长的计算时间。
2.sort by : sort by不是全局排序,其在数据进入reducer前完成排序,sort by只会保证每个reducer的输出有序,并不保证全局有序。sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。
3.distribute by : distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。sort by为每个reduce产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。
4.cluster by : cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒叙排序,不能指定排序规则为ASC或者DESC。

6.谈谈Hive的优化
1.Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算,在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
2.大小表join时,小表放在左边,可以有效避免OOM。
3.MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理
开启MapJoin参数设置:
(1)设置自动选择Mapjoin
set hive.auto.convert.join = true; 默认为true
(2)大表小表的阀值设置(默认25M以下认为是小表):
set hive.mapjoin.smalltable.filesize=25000000;
4.Group by
默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。
开启Map端聚合参数设置
(1)是否在Map端进行聚合,默认为True
hive.map.aggr = true
(2)在Map端进行聚合操作的条目数目
hive.groupby.mapaggr.checkinterval = 100000
(3)有数据倾斜的时候进行负载均衡(默认是false)
hive.groupby.skewindata = true
当选项设定为 true,生成的查询计划会有两个MR Job。第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。
5.Count(distinct)优化
数据量小的时候不需要优化处理,但是当数据量特别大的时候,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换。
6.行列过滤
列处理:只取需要的列,尽量不要使用select *
行处理:当两个表join时,需要加条件过滤时,将where条件加在on 前面。
7.并行执行
Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。

set hive.exec.parallel=true;              //打开任务并行执行
set hive.exec.parallel.thread.number=16;  //同一个sql允许最大并行度,默认为8。

8.严格模式
Hive提供了一个严格模式,可以防止用户执行那些可能意向不到的不好的影响的查询。
通过设置属性hive.mapred.mode值为默认是非严格模式nonstrict 。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止3种类型的查询。
1)对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行。换句话说,就是用户不允许扫描所有分区。进行这个限制的原因是,通常分区表都拥有非常大的数据集,而且数据增加迅速。没有进行分区限制的查询可能会消耗令人不可接受的巨大资源来处理这个表。
2)对于使用了order by语句的查询,要求必须使用limit语句。因为order by为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,强制要求用户增加这个LIMIT语句可以防止Reducer额外执行很长一段时间。
3)限制笛卡尔积的查询。对关系型数据库非常了解的用户可能期望在执行JOIN查询的时候不使用ON语句而是使用where语句,这样关系数据库的执行优化器就可以高效地将WHERE语句转化成那个ON语句。不幸的是,Hive并不会执行这种优化,因此,如果表足够大,那么这个查询就会出现不可控的情况。
9.SQL优化

1.去除查询中不需要的column
2.Where条件判断等在TableScan阶段就进行过滤
3.利用Partition信息,只读取符合条件的Partition
4.Map端join,以大表作驱动,小表载入所有mapper内存中
5.调整Join顺序,确保以大表作为驱动表
6.对于数据分布不均衡的表Group by时,为避免数据集中到少数的reducer上,分成两个map-reduce阶段。
第一个阶段先用Distinct列进行shuffle,然后在reduce端部分聚合,减小数据规模,
第二个map-reduce阶段再按group-by列聚合。
7.在map端用hash进行部分聚合,减小reduce端数据处理规模。
发布了27 篇原创文章 · 获赞 9 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/I_Demo/article/details/104277223