数仓简介及hive全面总结

1. 数据仓库主要特征

 数据仓库是面向主题的(Subject-Oriented)、集成的(Integrated)、稳定的(Non-Volatile)和时变的(Time-Variant)数据集合,用以支持管理决策。
主题性:指的是分析的需求
集成性:数据仓库中数据来源于各个数据源,将各个数据源聚合在一起
稳定性:存在数据仓库的数据,都是已经发生过得数据,这些数据不允许修改
时变性:随着时间的推移,数据也在不断的新增

2. 数据仓库(OLAP)与数据库(OLTP)区别

数据库
 数据库是面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理,也被称为联机事务处理 OLTP(On-Line Transaction Processing)。

数据仓库
 数据仓库一般针对某些主题的历史数据进行分析,支持管理决策,又被称为联机分析处理 OLAP(On-Line Analytical Processing)。
首先要明白,数据仓库的出现,并不是要取代数据库。
两者区别

  • 数据库是面向事务的设计,数据仓库是面向主题设计的。
  • 数据库一般存储业务数据,数据仓库存储的一般是历史数据。
  • 数据库设计是尽量避免冗余,一般针对某一业务应用进行设计,比如一张简单的User表,记录用户名、密码等简单数据即可,符合业务应用,但是不符合分析。数据仓库在设计是有意引入冗余,依照分析需求,分析维度、分析指标进行设计。
  • 数据库是为捕获数据而设计,数据仓库是为分析数据而设计。
    数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。

3. 数据仓库的分层

按照数据流入流出的过程,数据仓库架构可分为三层:源数据、数据仓库、数据应用

  • 源数据层(ODS):操作性数据(Operational Data Store),是作为数据库到数据仓库的一种过渡,ODS的数据结构一般与数据来源保持一致,而且ODS的数据周期比较短。
  • 数据仓库层(DW):数据仓库(Data WareHouse),是数据的归宿,这里保存着所有的从ODS到来的数据,并长期保存,而且这些数据不会被修改,DW层的数据应该是一致的、准确的、干净的数据,即对源数据进行了清洗后的数据。
  • 数据应用层(DA):数据应用(Data Application),为了特定的应用目的或应用范围,二从数据仓库中独立出来的一部分数据,也可称为部门数据或者主题数据,该数据面向应用

4. 数据仓库之ETL

 ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL是将业务系统的数据经过抽取、清洗、转换之后加载到数据仓库的过程,目的是将企业中分散、零乱、标准不统一的数据整合到一起。
 ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。

5. Hive的特点

① Hive最大的特点是通过SQL来分析大数据,而避免了写MapReduce程序来分析数据,使分析数据更简单。
② 数据是存储在HDFS上,Hive本身不提供数据存储功能,它可以使已存储的数据结构化。
③ Hive是将数据映射成数据库和一张张的表,库和表的元数据信息一般存在关系型数据库上(如MySQL)
④ 数据存储方面:它能存储很大的数据集,可以访问直接存储在Apache HDFS或者其它数据库存储系统(如HBASE)中的文件。
⑤ 数据处理方面:因为Hive语句最终会生成MapReduce任务去计算,所以不适用于实时计算的场景,它适用于离线计算分析。
⑥ Hive除了支持MapReduce计算引擎,还支持Spark和Tez这两种分布式计算引擎。
⑦ 数据的存储格式有多种,比如数据源是二进制格式,普通文本格式等等

6. Hive架构


基本组成:
客户端:Client CLI(hive shell命令行)、JDBC/ODBC(Java访问hive)、WEBUI(浏览器)
元数据:
MeteStore:元数据包括:表名、表所属数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等。
驱动器:Driver

  1. 解析器(SQL Parser):将SQL字符转换成抽象语法树AST,这一步一般使用第三方工具库完成。
  2. 编译器(Physical Plan):将AST编译生成逻辑执行计划
  3. 优化器(Query Optimizer):对逻辑执行计划进行优化
  4. 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划
    存储和执行:Hive用HDFS进行存储,用MapReduce进行计算

 元数据(metadata):本质上只是用来存储hive中有哪些数据库,哪些表,表的字段,分区,索引以及命名空间等元信息。元数据存储在关系型数据库中。如hive内置的Derby、第三方数据库如MySQL等。

 元数据服务(metastore),作用是:客户端连接metastore服务,metastore再去连接MySQL数据库来存取元数据。有了metastore服务,就可以有多个客户端同时连接,而且这些客户端不需要知道MySQL数据库的用户名和密码,只需要连接metastore 服务即可。

7. Hive的安装模式

 本地模式采用外部数据库来存储元数据,目前支持的数据库有:MySQL、Postgres、Oracle、MS SQL Server.在这里我们使用MySQL。
 本地模式不需要单独起metastore服务,用的是跟hive在同一个进程里的metastore服务。也就是说当你启动一个hive 服务,里面默认会帮我们启动一个metastore服务。
 hive根据hive.metastore.uris 参数值来判断,如果为空,则为本地模式。
缺点是:每启动一次hive服务,都内置启动了一个metastore。

 远程模式下,需要单独起metastore服务,然后每个客户端都在配置文件里配置连接到该metastore服务。远程模式的metastore服务和hive运行在不同的进程里。
 在生产环境中,建议用远程模式来配置Hive Metastore。
 在这种情况下,其他依赖hive的软件都可以通过Metastore访问hive

 远程模式下,需要配置hive.metastore.uris 参数来指定metastore服务运行的机器ip和端口,并且需要单独手动启动metastore服务。

8. Hive的交互方式

第一种交互方式:bin/hive

cd /export/servers/hive-2.1.0/
bin/hive

第二种交互方式:使用sql语句或者sql脚本进行交互
不进入hive的客户端直接执行hive的hql语句

cd /export/servers/hive-2.1.0/
bin/hive -e "create database mytest"

或者我们可以将我们的hql语句写成一个sql脚本然后执行

cd /export/servers
vim  hive.sql

脚本内容如下:

create database mytest2;
use mytest2;
create table stu(id int,name string);

通过hive -f 来执行我们的sql脚本

bin/hive -f /export/servers/hive.sql

第三种交互方式:Beeline Client
 hive经过发展,推出了第二代客户端beeline,但是beeline客户端不是直接访问metastore服务的,而是需要单独启动hiveserver2服务。
在hive运行的服务器上,首先启动metastore服务,然后启动hiveserver2服务。

nohup /export/servers/hive-2.1.0/bin/hive --service metastore &
nohup /export/servers/hive-2.1.0/bin/hive --service hiveserver2 &

nohup 和 & 表示后台启动

9. Hive各种表

内部表:未被external修饰的是内部表(managed table),内部表又称管理表,内部表数据存储的位置由hive.metastore.warehouse.dir参数决定(默认:/user/hive/warehouse),删除内部表会直接删除元数据(metadata)及存储数据,因此内部表不适合和其他工具共享数据。

外部表:在创建表的时候可以指定external关键字创建外部表,外部表对应的文件存储在location指定的hdfs目录下,向该目录添加新文件的同时,该表也会读取到该文件(当然文件格式必须跟表定义的一致)。 外部表因为是指定其他的hdfs路径的数据加载到表当中来,所以hive表会认为自己不完全独占这份数据,所以删除hive外部表的时候,数据仍然存放在hdfs当中,不会删掉。
内部表与外部表之间转换:

  1. 修改内部表A为外部表
alter table A set tblproperties('EXTERNAL'='TRUE');
  1. 修改外部表B为内部表
alter table B set tblproperties('EXTERNAL'='FALSE');
   注意:('EXTERNAL'='TRUE')和('EXTERNAL'='FALSE')为固定写法,区分大小写!

分区表:在大数据中,最常用的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天,或者每小时进行切分成一个个的小的文件,这样去操作小的文件就会容易得多了。

分桶表:将数据按照指定的字段进行分成多个桶中去,说白了就是将数据按照字段进行划分,可以将数据按照字段划分到多个文件当中去。
开启hive的桶表功能

set hive.enforce.bucketing=true;

 桶表的数据加载,由于桶表的数据加载通过hdfs dfs -put文件或者通过load data均不好使,只能通过insert overwrite 创建普通表,并通过insert overwrite的方式将普通表的数据通过查询的方式加载到桶表当中去

10. ORDER BY、Sort By、Distribute By、Cluster By区别:

Order By:全局排序,一个reduce
Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。
Distribute By:类似MR中partition,进行分区,结合sort by使用。
 注意,Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。
对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
Cluster By:当distribute by和sort by字段相同时,可以使用cluster by方式。
 cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒序排序,不能指定排序规则为ASC或者DESC。

11. Hive函数:

  • 数学函数:round、floor、pow、abs
  • 字符串函数:length、reverse、concat、concat_ws、substr,substring、upper,ucase、lower,lcase、trim、ltrim、rtrim、regexp_replace、parse_url、split
  • 日期函数:unix_timestamp、from_unixtime、unix_timestamp、to_date、year、month、day、weekofyear、datediff、date_add
  • 条件函数:if、CASE
  • 转换函数:cast()
  • 行转列:COLLECT_SET(col) 函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
  • 表生成函数:
    explode(col):将hive一列中复杂的array或者map结构拆分成多行。
    explode(ARRAY):列表中的每个元素生成一行
    explode(MAP):map中每个key-value对,生成一行,key为一列,value为一列
  • LATERAL VIEW侧视图:列转行
    用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
    解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
  • reflect函数
  • 开窗函数:NTILE,ROW_NUMBER,RANK,DENSE_RANK
  • 聚合函数:SUM,AVG,MIN,MAX
  • 分析窗口函数:LAG,LEAD,FIRST_VALUE,LAST_VALUE
  • 自定义函数:UDF、UDTF

12. 数据压缩方式:

1、gzip压缩
优点:压缩率比较高,而且压缩/解压速度也比较快;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;有hadoop native库;大部分linux系统都自带gzip命令,使用方便。
缺点:不支持split。
应用场景:当每个文件压缩之后在130M以内的(1个块大小内),都可以考虑用gzip压缩格式。譬如说一天或者一个小时的日志压缩成一个gzip文件,运行mapreduce程序的时候通过多个gzip文件达到并发。hive程序,streaming程序,和java写的mapreduce程序完全和文本处理一样,压缩之后原来的程序不需要做任何修改。
2、zlib压缩
类似于gzip压缩,支持orcfile格式,性能比gzip略高。
3、lzo压缩
优点:压缩/解压速度也比较快,合理的压缩率;支持split,是hadoop中最流行的压缩格式;支持hadoop native库;可以在linux系统下安装lzop命令,使用方便。
缺点:压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越越明显。
4、snappy压缩
优点:高速压缩速度和合理的压缩率;支持hadoop native库。
缺点:不支持split;压缩率比gzip要低;hadoop本身不支持,需要安装;linux系统下没有对应的命令。
应用场景:当mapreduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个mapreduce作业的输出和另外一个mapreduce作业的输入。
5、bzip2压缩
优点:支持split;具有很高的压缩率,比gzip压缩率都高;hadoop本身支持,但不支持native;在linux系统下自带bzip2命令,使用方便。
缺点:压缩/解压速度慢;不支持native。
应用场景:适合对速度要求不高,但需要较高的压缩率的时候,可以作为mapreduce作业的输出格式;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。

 在计算的过程中(DWD、DWM、DWS、APP),为了不影响执行的速度,可以浪费一点磁盘空间,采用orcfile+SNAPPY的方式,提升hive的执行速度。DWD明细层根据业务的需要,灵活选用ZLIB或SNAPPY。(根据实际业务选择)

13. Hive的数据存储格式:

  1. TEXTFILE
    Hive数据表的默认格式,存储方式:行存储。
    可以使用Gzip压缩算法,但压缩后的文件不支持split。
    在反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,因此反序列化开销会比SequenceFile高几十倍。
  2. SEQUENCEFILE
    压缩数据文件可以节省磁盘空间,但Hadoop中有些原生压缩文件的缺点之一就是不支持分割。支持分割的文件可以并行的有多个mapper程序处理大数据文件,大多数文件不支持可分割是因为这些文件只能从头开始读。Sequence File是可分割的文件格式,支持Hadoop的block级压缩。
    Hadoop API提供的一种二进制文件,以key-value的形式序列化到文件中。存储方式:行存储。
    sequencefile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,RECORD是默认选项,通常BLOCK会带来较RECORD更好的压缩性能。
    优势是文件和hadoop api中的MapFile是相互兼容的。
  3. RCFILE
    存储方式:数据按行分块,每块按列存储。结合了行存储和列存储的优点:
    RCFile 保证同一行的数据位于同一节点,因此元组重构的开销很低
    像列存储一样,RCFile 能够利用列维度的数据压缩,并且能跳过不必要的列读取
    数据追加:RCFile不支持任意方式的数据写操作,仅提供一种追加接口,这是因为底层的 HDFS当前仅仅支持数据追加写文件尾部。
    行组大小:行组变大有助于提高数据压缩的效率,但是可能会损害数据的读取性能,因为这样增加了 Lazy 解压性能的消耗。而且行组变大会占用更多的内存,这会影响并发执行的其他MR作业。 考虑到存储空间和查询效率两个方面,Facebook 选择 4MB 作为默认的行组大小,当然也允许用户自行选择参数进行配置。
  4. ORCFILE
    存储方式:数据按行分块,每块按照列存储。 是rcfile的改良版本,效率比rcfile高,压缩快,更快速的列存/取。

14. Hive调优:

  • a. Fetch抓取:Hive在某些情况的查询可以不必使用MapReduce计算。在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
  • b. 本地模式:在hive输入数据量非常小时,hive可以通过本地模式在单台机器上处理所有任务
  • c. Join优化:
    大小表join:用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理
    大表join大表:
    空key过滤
    空key转换:赋一个随机的值
  • d. SQL优化:
    列裁剪:只读取查询中所需要用到的列
    分区裁剪:查询的过程中减少不必要的分区
    Group by:可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。
    参数设置开启map端聚合
    COUNT DISTINCT:数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换
    笛卡尔积:尽量避免笛卡尔积,即避免join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。
  • e. 动态分区调整
    往hive分区表中插入数据时,hive提供了一个动态分区功能,其可以基于查询参数的位置去推断分区的名称,从而建立分区。使用Hive的动态分区,需要进行相应的配置。
    Hive的动态分区是以第一个表的分区规则,来对应第二个表的分区规则,将第一个表的所有分区,全部拷贝到第二个表中来,第二个表在加载数据的时候,不需要指定分区了,直接用第一个表的分区即可
    参数设置
    (1)开启动态分区功能(默认true,开启)
 set hive.exec.dynamic.partition=true;

(2)设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。)

set hive.exec.dynamic.partition.mode=nonstrict;

(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。

set  hive.exec.max.dynamic.partitions=1000;

(4)在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。

set hive.exec.max.dynamic.partitions.pernode=100

(5)整个MR Job中,最大可以创建多少个HDFS文件。
在linux系统当中,每个linux用户最多可以开启1024个进程,每一个进程最多可以打开2048个文件,即持有2048个文件句柄,下面这个值越大,就可以打开文件句柄越大

set hive.exec.max.created.files=100000;

(6)当有空分区生成时,是否抛出异常。一般不需要设置。

set hive.error.on.empty.partition=false;
  • f. 调整合适的map数
    增加map数:一个文件小于一个block块大小(假如127M),但是这个文件,只有一两个字段,却存有几千万个记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定是非常耗时的,这时就需要适当增加map数。
    减少map数:当一个任务有很多小文件,文件大小又远远小于block块大小,每个文件也会被当作一个快,用一个map处理,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。这时就需要减少map数。
  • g. 设置合适的reduce数
    Reduce的个数对整个作业的运行性能有很大影响。如果Reduce设置的过大,那么将会产生很多小文件,对NameNode会产生一定的影响,而且整个作业的运行时间未必会减少;如果Reduce设置的过小,那么单个Reduce处理的数据将会加大,很可能会引起OOM异常。
  • h. 并行执行
    Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。
    通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。
  • i. 严格模式
    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并不会执行这种优化,因此,如果表足够大,那么这个查询就会出现不可控的情况。
  • j. JVM重用
    JVM重用是Hadoop调优参数的内容,其对Hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或task特别多的场景,这类场景大多数执行时间都很短。
    Hadoop的默认配置通常是使用派生JVM来执行map和Reduce任务的。这时JVM的启动过程可能会造成相当大的开销,尤其是执行的job包含有成百上千task任务的情况。JVM重用可以使得JVM实例在同一个job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间,具体多少需要根据具体业务场景测试得出。
  • k. 推测执行
    在分布式集群环境下,因为程序Bug(包括Hadoop本身的bug),负载不均衡或者资源分布不均等原因,会造成同一个作业的多个任务之间运行速度不一致,有些任务的运行速度可能明显慢于其他任务(比如一个作业的某个任务进度只有50%,而其他所有任务已经运行完毕),则这些任务会拖慢作业的整体执行进度。为了避免这种情况发生,Hadoop采用了推测执行(Speculative Execution)机制,它根据一定的法则推测出“拖后腿”的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最先成功运行完成任务的计算结果作为最终结果。
  • l. 存储方式和压缩方式
    大数据场景下存储格式压缩格式尤为关键,可以提升计算速度,减少存储空间,降低网络io,磁盘io,所以要选择合适的压缩格式和存储格式

15. hive小文件过多问题

哪里会产生小文件 ?

  • 源数据本身有很多小文件
  • 动态分区会产生大量小文件
  • reduce个数越多, 小文件越多
  • 按分区插入数据的时候会产生大量的小文件, 文件个数 = maptask个数 * 分区数

小文件太多造成的影响 ?

  • 从Hive的角度看,小文件会开很多map,一个map开一个JVM去执行,所以这些任务的初始化,启动,执行会浪费大量的资源,严重影响性能。
  • HDFS存储太多小文件, 会导致namenode元数据特别大, 占用太多内存, 制约了集群的扩展

小文件解决方法

  • 方法一: 通过调整参数进行合并(设置map输入/输出、reduce输出等相关参数)
#每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;

#一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;

#一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100000000;

#执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

#===设置map输出和reduce输出进行合并的相关参数:

#设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true

#设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true

#设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000

#当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set hive.merge.smallfiles.avgsize=16000000
  • 方法二: 针对按分区插入数据的时候产生大量的小文件的问题, 可以使用DISTRIBUTE BY rand() 将数据随机分配给Reduce,这样可以使得每个Reduce处理的数据大体一致.
# 设置每个reducer处理的大小为5个G
set hive.exec.reducers.bytes.per.reducer=5120000000;

# 使用distribute by rand()将数据随机分配给reduce, 避免出现有的文件特别大, 有的文件特别小
insert overwrite table test partition(dt)
select * from iteblog_tmp
DISTRIBUTE BY rand();
  • 方法三: 使用Sequencefile作为表存储格式,不要用textfile,在一定程度上可以减少小文件

  • 方法四: 使用hadoop的archive归档

#用来控制归档是否可用
set hive.archive.enabled=true;
#通知Hive在创建归档时是否可以设置父目录
set hive.archive.har.parentdir.settable=true;
#控制需要归档文件的大小
set har.partfile.size=1099511627776;

#使用以下命令进行归档
ALTER TABLE srcpart ARCHIVE PARTITION(ds='2008-04-08', hr='12');

#对已归档的分区恢复为原文件
ALTER TABLE srcpart UNARCHIVE PARTITION(ds='2008-04-08', hr='12');

#::注意,归档的分区不能够INSERT OVERWRITE,必须先unarchive

补充: hadoop自带的三种小文件处理方案 – Hadoop Archive,Sequence file和CombineFileInputFormat.

  • Hadoop Archive
    Hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。

  • Sequence file
    sequence file由一系列的二进制key/value组成,如果为key小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。

  • CombineFileInputFormat
    它是一种新的inputformat,用于将多个文件合并成一个单独的split,另外,它会考虑数据的存储位置。

你可能感兴趣的:(Hive,hive)