参考《Hive实战》
ASF是一个支持多种软件开发项目的组织
Hive不是数据库,而是一个友好且为我们熟悉的接口,可以查询存储在HDFS上的底层数据文件
SerDe:序列化、反序列化
HCatlog促进了各种Hadoop组件之间实现模式共享,HCatlog的作用包括:
- 为多种工具提供一种通用模式环境
- 允许各种工具通过连接器连接,进而从Hive仓库读取数据和向其写入数据
- 使用户可以跨工具共享数据
- 为Hadoop中的数据创建一种关系结构
- 抽象出数据存储的方式和位置
- 使模式和存储的更改对用户不可见
HCatlog本质上是数据访问工具与底层文件之间的抽象层
HiveServer1的限制:用户并发性、LDAP安全性集成
HiveServer2 架构基于一个ThriftService和任意数量由驱动程序、编译器和执行器组成的会话。MetaStore也是HiveServer2的一个重要组成部分
支持Kerberos、自定义身份验证以及通过LDAP身份验证
HiveServer2在Hive1.1引入(HIVE-2935),提供更好的并发性、安全性、远程访问
内部表 & 外部表:
- 内部表由Hive自身管理,外部表数据为HDFS管理
- 内部表数据存在hive.metastore.warehouse.dir,外部表数据存储自己指定位置
- 删除内部表会直接删除元数据和存储数据,删除外部表仅仅删除元数据,HDFS不会删除
- 对内部表的修改会同步给元数据,对外部表的修改需要修复(MSCK REPAIR table xxx)
Tez:
- 避免了代价高昂的混洗过程,因此避免了磁盘IO。在Tez执行引擎的执行计划中,简约器的中间数据将直接传递给下一个简约器
- 采用了高效的Map端连接
- 采用了基于代价的优化器,有助于生成更快的执行计划
- Tez与ORC文件格式联合使用,查询引擎的执行速度比本机MR快100倍
Tez相关配置:
hive.prewarm.enabled = true //Hive创建Tez容器
hive.prewarm.numcontainers //调整Tez专用容器的数量
表的属性(TBLPROPERTIES):
- last_modified_user:
- last_modified_time:
- immutable:为true时,无法在插入新行
- orc.compress:
- skip.header.line.count:调过底层数据的标题行
用show create table 生成创建表语句
分区最佳实践:
- 挑选一列作为分区键,其唯一值的个数应在较低值到中间值之间
- 避免分区小于1GB(越大越好)
- 当分区数量较多时,调整HiveServer2 和 Hive MetaStore的内存
- 当使用多列作为分区键时,对于每一个分区键列的组合都要创建一个子目录的嵌套树
- 当使用Hive流处理插入数据时,如果多个会话向相同分区插入数据,那么会导致锁闭
- 一旦分区表的模式发生改变,将无法在已有分区上修改数据
- 如果要将数据并行插入到多个分区,应该将hive.optimize.sort.dynamic.partition设置为true
对于日期列进行高效分区:
select * from table A where datestamp in ('2015-01-01','2015-02-03','2016-01-01');
select * from table A where datestamp like '2015-%';
select * from table A where datestamp like '2015-02-%';
select * from table A where datestamp like '%-%-%5';
select * from table A where datestamp between '2015-01-01' AND '2015-03-01'
schema - on - read
添加分区:
alter table add partition;
alter table xxx partition(xx) rename to partition(yy);
分桶:
- Hive中的分桶是另一种将数据切分为更小片段的方式
- 分区键是表中的一个虚拟列,然而在分桶中,每个桶都是一个保存实际数据的文件,这些数据基于一种散列算法进行分割,分桶并不会为当前表添加一个虚拟列
create table xx(xxxxxx) clusted by (xxx) into xx buckets location 'xxx'
分桶的最佳实践:
- 选择唯一值的个数较多的桶键。这样会减小出现倾斜的可能性
- 采用质数作为桶的编号
- 如果桶键中的数据是倾斜的,为倾斜的值单独创建桶。可以通过列表分桶来实现
- 需要连接在一起的表,桶的数目必须相同,或者一个表的桶数是另一个表的桶数的因子
- 一个CPU只会对一个桶进行写入操作,如果桶的数目很小,集群的利用严重不足
- 一旦表创建好,桶的数目就不能改变了
- 桶文件大小至少是1GB
- 通过设置hive.enforce.bucketing = true 实现强制分桶
- 对于map端连接,分桶表要比非分桶表的速度更快
Parquet:Parquet文件是以二进制方式存储的,是不可以直接读取和修改的,Parquet文件是自解析的,文件中包括该文件的数据和元数据。在HDFS文件系统和Parquet文件中存在如下几个概念:
- HDFS块(Block):它是HDFS上的最小的副本单位,HDFS会把一个Block存储在本地的一个文件并且维护分散在不同的机器上的多个副本,通常情况下一个Block的大小为256M、512M等。
- HDFS文件(File):一个HDFS的文件,包括数据和元数据,数据分散存储在多个Block中。
- 行组(Row Group):按照行将数据物理上划分为多个单元,每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,Parquet读写的时候会将整个行组缓存在内存中,所以如果每一个行组的大小是由内存大的小决定的。
- 列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。不同的列块可能使用不同的算法进行压缩。
- 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式
p243 图
ORC:(Parquet不如ORC)
ORC文件格式用于减少要从磁盘读取的数据量(基于列),可以被分割的文件格式,可以分割成多个可并行处理的块。
数据按行组切分,一个行组包含若干行,每行中再按列存储(256MB的数据带)
create table xxx stored as orc tblproperties("orc.compress"="snappy") as select * from xxx
ORC文件:保存在文件系统上的普通二进制文件,一个ORC文件中可以包含多个stripe,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念
ORC格式相关的配置:
- orc.compress
- orc.compress.size
- orc.stripe.size 每个带的字节数
- orc.row.index.stride 索引记录之间的行数
- orc.create.index 是否要创建行索引
- hive.exec.orc.default.block.size
- hive.exec.orc.default.stripe.size
文件级元数据:包括文件的描述信息PostScript、文件meta信息(包括整个文件的统计信息)、所有stripe的信息和文件schema信息
orc三个层级信息:
- 文件级别:记录了文件中所有stripe的位置信息
- stripe级别:每个stripe所存储数据的统计信息
- row group级别:每10000行构成一个行组
- stripe(行):一组行形成一个stripe,每次读取文件是以行组为单位的,一般为HDFS的块大小,保存了每一列的索引和数据
- stripe元数据:保存stripe的位置、每一个列的在该stripe的统计信息以及所有的stream类型和位置。
- row group:索引的最小单位,一个stripe中包含多个row group,默认为10000个值组成。
- stream(列):一个stream表示文件中一段有效的数据,包括索引和数据两类。索引stream保存每一个row group的位置和统计信息,数据stream包括多种类型的数据,具体需要哪几种是由该列类型和编码方式决定
orc划分多个block块,每个orc block横向切分成多个stripes(一组行对应一个stripe),每个stripe内部以列stream为单位存储
p238 图
数据查找过程:
- 列索引 -----> 找到文件
- 文件索引 ----> 找到stripe,并通过stripe索引找到stripe块
- stripe中的行组索引 ----> 找到行组
ORC所有类型都接受NULL值
ORC能确保Hive在工作时事务的支持
参考:https://blog.csdn.net/yu616568/article/details/51868447
CBO:
Hive的more查询执行引擎一次处理一行,因此在嵌套循环中需要有多层虚拟方法调用,从CPU的视角来看是非常低效的。
矢量化查询执行是一种Hive特性,其目的是按照每批1024行读取数据,并且一次性对整个记录集合应用操作,进而消除那些效率低下的问题。必须使用ORC格式,CBO帮助生成一个最优执行计划,在该计划的执行过程中,从磁盘读取和处理的数据量已经尽可能早地减少,使工作更加高效
set hive.vectorized.execution.enabled = true;
合并表文件:
对于RCFile 或 ORCFile 格式存储的Hive表,可以做如下操作:alter table states concatenate
该命令会将多个数据文件合并成较大的文件
单次MapReduce实现连接:
select xxx from table_A join table_B
on (table_A.xxx = table_B.xxx)
join table_C
on (table_C.xxx = tableB.xxx)
Apache NiFi:
适用于各种类型的数据装载和摄入场景,提供了对数据传输作业进行设计、控制、管理和监视的无缝体验
Hive对JSON数据的处理
1.使用UDF处理
create table json_table(json string);
load data inpath 'xxxx' into table json_table;
select get_json_object(json_table.json,'$') from json_table;
2.使用SerDe处理json
create table json_serde_table(xxxxxx)row format serde 'org.openx.data.jsonserde.JsonSerDe' with SERDEPROPERTIES("mapping._id" = "id");
load data inpath 'xxx' into table json_serde_table;
select * from json_serde_table;
LLAP
对亚秒级查询需求快速的查询执行和降低整个生态系统内任务的设置成本
附 Hive源码线程池:
- HiveServer有两个线程池,客户端Connection对应的是HiveServer2-Handler-Pool,在ThriftBinaryCLIService中创建,最大线程数由hive.server2.thrift.max.worker.threads控制
- 后台处理的线程池是HiveServer2-Background-Pool,在SessionManager中创建,最大线程数如果是安全版本,由hive.server.session.control.maxconnections控制,非安全版本由hive.server2.async.exec.threads控制
insert into & insert overwrite 区别
- insert into:以追加的方式向hive表尾追加数据
- insert overwrite:直接重写数据,先删除hive表的数据,再执行写入操作
multipleoutput:通过MultipleOutputs写到多个文件 - 刘超★ljc - 博客园
Hive archive:HIVE ARCHIVE__final__的博客-CSDN博客_hive.archive.enabled
Hive shims: 腾讯云 - 产业智变 云启未来