一:Hive简介
Hive是构建在hadoop上的数据仓库,可以把结构化的数据文件映射成表,并提供SQL查询功能,用于查询的SQL语句会被转成MapReduce 任务提交到hadoop上运行。
Hive出现的原因?
面对海量数据的分析hadoop是个好东西,但是学习成本比较高,难度大,需要使用人员得会编程,相比编程,SQL的学习成本较低,简单,易上手,于是hive就出现了。
优点:
- 简单,易上手,使得会SQL但不懂编程的人员可以对海量数据进行分析。
- 统一的元数据管理,可与 sparkSQL/impala等共享数据。
- 灵活性高,可以自定义用户函数(UDF)和存储格式。
缺点:
- 延迟性高,不适合做数据的实时处理,但适合做海量数据的离线处理。
数据库与数据仓库的区别?
功能 | 数据库 | 数据仓库 |
应用场景 | 维持业务正常运转的操作类的数据 | 面向分析,支持侧重决策分析 |
数据范围 | 当前状态数据 | 存储历史、完整、反应历史变化的数据 |
数据变化 | 支持频繁的增删改查操作 | 可增加,查询,无删除更新操作 |
处理数据量 | 频繁、小批次、高并发、低延迟 | 非频繁、大批量、高吞吐、有延迟 |
设计理论 | 遵循数据库三范式,避免冗余 | 违范式,适当冗余 |
建模方式 | 范式建模 | 范式建模+维度建模 |
二:Hive架构
了解一个技术的架构,首先从角色入手,架构中有哪些角色以及每个角色的功能
用户访问接口
Cli (Command Line Interface):用户可以使用Hive自带的命令行接口执行Hive QL、设置参数等功能
JDBC/ODBC :用户可以使用基于Thrift协议的JDBC或者ODBC的方式在代码中操作Hive
Web GUI:浏览器接口,用户可以在浏览器中对Hive进行操作(2.2之后淘汰)
MetaStore
Hive 中的元数据通常包括:表的名字,表的列和分区及其属性,表的属性(内部表和 外部表),表的数据所在目录
Metastore 默认存在自带的 Derby 数据库中。Derby是一个内存数据库,不能持久化,不适合多用户操作,并且数据存储目录不固定。数据库跟着 Hive 走,极度不方便管理
在实际的生产环境中一般使用MySQL代替Derby
Driver
Hive Driver是Hive的核心,包括解析器、编译器、执行器、优化器,完成从SQL语句到MapReduce任务的解析优化执行过程
HDFS
Hive的数据存储在Hdfs上
三:Hive的搭建模式
(1)使用默认的Derby数据库
(2)使用远程数据库
(3)使用远程服务器模式,在服务器端启动MetaStoreServer,客户端使用Thrift协议通过MetaStoreServer访问数据库,实现了hive与MetaStore的解耦,另外把元数据抽象成一个服务,spark-sql 也可以使用
四:HQL的执行过程
语法解析:Antlr定义SQL的语法规则,完成SQL的词法,语法解析,将SQL转化为抽象语法树AST Tree
语义解析:遍历AST Tree,抽象出查询的基本组成单元QueryBlock
生成逻辑执行计划:遍历 QueryBlock,翻译为执行操作树 OperatorTree
优化逻辑执行计划:逻辑层优化器进行 OperatorTree 变换,合并不必要的 ReduceSinkOperator,减少 shuffle 数据量。
生成物理执行计划:遍历 OperatorTree,翻译为 MapReduce 任务
优化物理执行计划:物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划
五:Hive的执行过程
(1)执行查询
用户通过Hive访问接口将查询发送给Driver
(2)获取计划
Driver借助查询编译器解析SQL,检查语法和查询需求
(3)获取元数据
编译器将获取元数据请求发送给MetaStore
(4)发送元数据
MetaStore将元数据作为对编译器的响应发送出去
(5)发送计划
编译器检查需求并将计划重新发送给Driver,到目前为止,查询的解析和编译已经完成
(6)执行计划
Driver将执行计划发送给执行引擎
(7)执行结果
在内部,执行任务的过程是MapReduce Job。执行引擎将Job发送到ResourceManager(在这里注意,执行器在执行方案时,会判断:如果当前方案不涉及到MR组件,比如为表添加分区信息、比如字符串操作等,比如简单的查询操作等,此时就会直接和元数据库交互,然后去HDFS上去找具体数据。如果方案需要转化成MR job),ResourceManager位于NameNode节点中,并将job分配给DataNode中的NodeManager。在这里,查询执行MapReduce任务。在执行的同时,执行引擎可以使用Metastore执行元数据操作。
(8)获取结果
执行引擎从DataNode获取结果集
(9)发送结果给Driver
执行引擎将结果发送给Driver
(10)发送结果给用户
Driver将结果发送到Hive接口
六:Hive的压缩和存储
1. Hadoop压缩配置
(1)MR支持的压缩编码
压缩格式 | 算法 | 文件扩展名 | 是否切片 | 换成压缩格式后,原来的程序是否需要修改 |
DEFLATE | DEFLATE | .deflate | 否 | 和文本处理一样,不需要修改 |
GZIP | DEFLATE | .gz | 否 | 和文本处理一样,不需要修改 |
BZIP2 | BZIP2 | .bz2 | 是 | 和文本处理一样,不需要修改 |
LZO | LZO | .lzo | 是 | 需要建索引,还需要指定输入格式 |
SNAPPY | SNAPPY | .snappy | 否 | 和文本处理一样,不需要修改 |
为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示
压缩格式 | 对应的编码/解释器 |
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
GZIP | org.apache.hadoop.io.compress.GzipCodec |
BZIP2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
SNAPPY | org.apache.hadoop.io.compress.SnappyCodec |
(2)压缩配置参数
要在Hadoop中启用压缩,可以配置如下参数(mapred-site.xml文件中):
参数 | 默认值 | 阶段 | 建议 |
io.compression.codecs (在core-site.xml中配置) | org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec, org.apache.hadoop.io.compress.Lz4Codec | 输入压缩 | Hadoop使用文件扩展名判断是否支持某种编解码器 |
mapreduce.map.output.compress | false | mapper输出 | 这个参数设为true启用压缩 |
mapreduce.map.output.compress.codec | org.apache.hadoop.io.compress.DefaultCodec | mapper输出 | 使用LZO、LZ4或snappy编解码器在此阶段压缩数据 |
mapreduce.output.fileoutputformat.compress | false | reducer输出 | 这个参数设为true启用压缩 |
mapreduce.output.fileoutputformat.compress.codec | org.apache.hadoop.io.compress. DefaultCodec | reducer输出 | 使用标准工具或者编解码器,如gzip和bzip2 |
mapreduce.output.fileoutputformat.compress.type | RECORD | reducer输出 | SequenceFile输出使用的压缩类型:NONE和BLOCK |
(3)开启Map输出阶段压缩
开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下:
--1)开启hive中间传输数据压缩功能
hive (default)>set hive.exec.compress.intermediate=true;
--2)开启mapreduce中map输出压缩功能
hive (default)>set mapreduce.map.output.compress=true;
--3)设置mapreduce中map输出数据的压缩方式
hive (default)>set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
--4)执行查询语句
hive (default)> select count(*) from aaaa;
(4)开启Reduce输出阶段压缩
当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性hive.exec.compress.output控制着这个功能。用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。
--1)开启hive最终输出数据压缩功能
hive (default)>set hive.exec.compress.output=true;
--2)开启mapreduce最终输出数据压缩
hive (default)>set mapreduce.output.fileoutputformat.compress=true;
--3)设置mapreduce最终数据输出压缩方式
hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
--4)设置mapreduce最终数据输出压缩为块压缩
hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;
--5)测试一下输出结果是否是压缩文件
hive (default)> insert overwrite local directory '/root/data' select * from aaaa;
2. 文件存储格式
格式 | 说明 |
TEXTFILE | 存储为纯文本文件,默认存储格式。不做压缩,磁盘开销大,数据解析开销大 |
SEQUENCEFILE | SequenceFile 是 Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。这种二进制文件内部使用 Hadoop 的标准的 Writable 接口实现序列化和反序列化。它与 Hadoop API 中的 MapFile 是互相兼容的。Hive 中的 SequenceFile 继承自 Hadoop API 的 SequenceFile,不过它的 key 为空,使用 value 存放实际的值,这样是为了避免 MR 在运行 map 阶段进行额外的排序操作。 |
RCFILE | RCFile 文件格式是 FaceBook 开源的一种 Hive 的文件存储格式,首先将表分为几个行组,对每个行组内的数据按列存储,每一列的数据都是分开存储。 |
ORC FILES | ORC 是在一定程度上扩展了 RCFile,是对 RCFile 的优化。 |
AVRO FILES | Avro 是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro 提供的机制使动态语言可以方便地处理 Avro 数据。 |
PARQUET | Parquet 是基于 Dremel 的数据模型和算法实现的,面向分析型业务的列式存储格式。它通过按列进行高效压缩和特殊的编码技术,从而在降低存储空间的同时提高了 IO 效率。 |
行存储的特点: 查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。
列存储的特点: 因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。
TEXTFILE和SEQUENCEFILE的存储格式都是基于行存储的;
ORC和PARQUET是基于列式存储的。
主流文件存储格式对比实验
--1)TextFile
--(1)创建表,存储数据格式为TEXTFILE
create table log_text (track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t'stored as textfile ;
--(2)向表中加载数据
hive (default)> load data local inpath '/root/log' into table log_text ;
--(3)查看表中数据大小
dfs -du -h /user/hive/warehouse/log_text;
18.1 M /user/hive/warehouse/log_text/log.data
--2)ORC
--(1)创建表,存储数据格式为ORC
create table log_orc(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t'stored as orc ;
--(2)向表中加载数据
insert into table log_orc select * from log_text ;
--(3)查看表中数据大小
dfs -du -h /user/hive/warehouse/log_orc/ ;
2.8 M /user/hive/warehouse/log_orc/000000_0
--3)Parquet
--(1)创建表,存储数据格式为parquet
create table log_parquet(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t'stored as parquet ;
--(2)向表中加载数据
insert into table log_parquet select * from log_text ;
--(3)查看表中数据大小
dfs -du -h /user/hive/warehouse/log_parquet/ ;
13.1 M /user/hive/warehouse/log_parquet/000000_0
--存储文件的压缩比总结:
ORC > Parquet > textFile
3. 存储和压缩相结合
key | default | notes |
orc.compress | ZLIB | high level compression (one of NONE, ZLIB, SNAPPY) |
orc.compress.size | 262,144 | number of bytes in each compression chunk |
orc.stripe.size | 67,108,864 | number of bytes in each stripe |
orc.row.index.stride | 10,000 | number of rows between index entries (must be >= 1000) |
orc.create.index | true | whether to create row indexes |
orc.bloom.filter.columns | "" | comma separated list of column names for which bloom filter should be created |
orc.bloom.filter.fpp | 0.05 | false positive probability for bloom filter (must >0.0 and <1.0) |
--1)创建一个非压缩的的ORC存储方式
--(1)建表语句
create table log_orc_none(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t'stored as orc tblproperties ("orc.compress"="NONE");
--(2)插入数据
insert into table log_orc_none select * from log_text ;
--(3)查看插入后数据
dfs -du -h /user/hive/warehouse/log_orc_none/ ;
7.7 M /user/hive/warehouse/log_orc_none/000000_0
--2)创建一个SNAPPY压缩的ORC存储方式
--(1)建表语句
create table log_orc_snappy(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t'stored as orc tblproperties ("orc.compress"="SNAPPY");
--(2)插入数据
insert into table log_orc_snappy select * from log_text ;
--(3)查看插入后数据
dfs -du -h /user/hive/warehouse/log_orc_snappy/ ;
3.8 M /user/hive/warehouse/log_orc_snappy/000000_0
--3)上一节中默认创建的ORC存储方式,导入数据后的大小为
2.8 M /user/hive/warehouse/log_orc/000000_0
--总结
比Snappy压缩的还小。原因是orc存储文件默认采用ZLIB压缩。比snappy压缩的小。