Hive的架构和操作

hive简介

直接使用hadoop所面临问题

为什么使用hive

hive架构

基本组成

各组件功能

Hive利用HDFS存储,利用MapReduce查询数据

Hive的数据存储

  1. Hive 中所有的数据都存储在 HDFS 中,没有专门的数据存储格式(可支持Text,SequenceFile,ParquetFile,RCFILE等)。
  2. 只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。
  3. Hive 中包含以下数据模型:DB、Table、External Table、 Partition、 Bucket。
    1. db:在hdfs中表现为${hive.metastore.warehouse.dir}目录下一个文件夹
    2. table:在hdfs中表现所属db目录下一个文件夹
    3. external table:与table类似,不过其数据存放位置可以在任意指定路径
    4. partition:在hdfs中表现为table目录下的子目录
    5. bucket:在hdfs中表现为同一个表目录下根据hash散列之后的多个文件

使用方式

Hive thrift服务

mark
启动方式:

启动成功,可以在别的节点上用beeline去链接:

表分区或分桶的理由

把表(或者分区)组织成桶(Bucket)有两个理由:

  1. 分区是独立一列为分区列,是为了获得更高的查询处理效率。
  2. 桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。
    • 具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如join操作。对于join操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
  3. 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

Hive函数区别

Hive表结构

分区表

一般结构,单层分区

create table partition_access_log (ip STRING, ) 
....
partitioned by (request_date STRING) ...;

hdfs:///access_logs/....
    - 2018_11_06
    - 2018_11_07
    - 2018_11_08

多层分区

create table partitioned_access_long (ip STRING, )....
partition by (year STRING, moneth STRING, day STRING) ...;

分区表作用:

分区表加载数据

静态分区:

from raw_accesss_log
insert overwrite table partitioned_access_log
partition(year="2017", month="03", day="25")
select ip, .......

动态分区

from raw_access_log
insert overwrite table 
partitioned_access_log
partition(year, month, day)
select ip, ..., year, month, day
insert overwrite table 
partitioned_access_log
partition(year, month, day)
select ip, ..., year, month, day
from raw_access_log

混合模式

from raw_access_log
insert overwrite table partitioned_access_log
partition (year="2017", month, day)
select ip,...., month day

分区动态加载数据参数

set  hive.exec.max.dynamic.partitions=2048;
set  hive.exec.max.dynamic.partitions.pernode=256;
set  hive.exec.max.created.files=10000;
# 防止空的分区产生
set hive.error.on.empty.partition=true; 
# 允许动态分区
set hive.exec.dynamic.partition.mode=nonstrict;

表分桶

create table granular_access_log( ip STRING, )...
partition by (request_date STRING)
clustered by (column_name, ...)
into 200 buckets ...;

clustered by (user_id)
hash函数:INT是取模,STRING 能保证平均分布

如果分桶和sort字段是同一个时,此时,cluster by = distribute by + sort by

分桶表的作用:最大的作用是用来提高join操作的效率;

分桶表写入数据

hive并不检查数据文件中的桶是否和表定义的桶一致。如果两者不匹配,查询时可能会碰到错误。

  1. 首先要把reduce的数据定义为buckets数据一致,即决定最终会产生多少个文件
  2. hive.enforce.sorting 和 hive.enforce.bucketing都设置为true, 就不需要手动添加distribute by 和 sort by
set mapred.reduce.tasks = 200;
from raw_access_log
insert overwrite table granular_access_log partition by (request_date)
select ..., request_date
where ...
distribute by user_id
[sort by user_id];

set hive.enforce.bucketing=true;
from raw_access_log
insert overwrite table granular_access_log partition by(request_date) 
select ..., request_date
where ...;
  1. order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
  2. sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并设置mapred.reduce.tasks>1, 则sort by只保证每个reducer的输出有序,不保证全局有序。
  3. distribute by(字段) 根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
  4. Cluster by(字段) 除了具有Distribute by的功能外,还会对该字段进行排序。
SMB
  1. 需要在每个桶内按相同字段排序
  2. 打开设置
hive> SET hive.auto.convert.sortmerge.join=true

存储格式

Hive 从两个维度对表的存储进行管理,分别是行格式(row format)和文件格式(file format)。

SerDe:是“序列化和反序列化工具”的合成词。当作为反序列化工具进行使用时,也就是查询表时,SerDe将把文件中字节形式的数据行反序列为Hive内部操作数据行时所用的对象形式。

1. 默认存储格式:分隔的文本

file.default.fileformat

创建表时,没有使用row format 或 store as 子句,那么hive 使用的是默认分隔。默认分隔符不是制表符 ,而ASCII控制 码集合中的Control-A(它的ASCII码为1 也就是 \001)

create table ...

等价于

create table ...
row format delimited
  fields terminated by '\001'
  collection items terminated by '\002'
  map keys terminated by '\003'
  lines terminated by '\n'
 stored as textfile;