hive的存储格式

时间:2024-12-17 07:10:39

1) 四种存储格式

hive的存储格式分为两大类:一类纯文本文件,一类是二进制文件存储。

Hive支持的存储数据的格式主要有:TEXTFILE、SEQUENCEFILE、ORC、PARQUET

第一类:纯文本文件存储

textfile: 纯文本文件存储格式,不压缩,也是hive的默认存储格式,磁盘开销大,数据解析开销大

第二类:二进制文件存储

- sequencefile:

会压缩,不能使用load方式加载数据

- parquet:

会压缩,不能使用load方式加载数据

- rcfile:

会压缩,不能load。查询性能高,写操作慢,所需内存大,计算量大。此格式为行列混合存储,hive在该格式下,会尽量将附近的行和列的块存储到一起。

- orcfile:rcfile的升级版。

2)列式存储和行式存储

TEXTFILE和SEQUENCEFILE的存储格式都是基于行存储的;

ORC和PARQUET是基于列式存储的。

行式存储:查找某一条整行数据比较快

列式存储:查找某个字段比较快 select name from user;

修改hive的默认存储格式:

<property>
  <name>hive.default.fileformat</name>
  <value>TextFile</value>
  <description>
    Expects one of [textfile, sequencefile, rcfile, orc].
    Default file format for CREATE TABLE statement. Users can explicitly override it by CREATE TABLE ... STORED AS [FORMAT]
  </description>
</property>

也可以使用set方式修改:
set hive.default.fileformat=TextFile

3)实操一下:

首先将一个18.1M的数据上传至 /home/hivedata/,这个文件叫做stocks.log

textfile类型演示:

create table stocks_1 (
  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;

load data local inpath '/home/hivedata/stocks.log' into table stocks_1;
在linux的命令行上使用hdfs dfs -put方法去上传到指定目录下。

可以查看到数据,说明是文本类型的。

sequencefile 的使用

create external table if not exists stocks_seq_1 (
  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 sequencefile;

由于不能load数据,从普通表中查询出来插入进入。
使用insert into的方式加载数据
insert into stocks_seq_1 select * from stocks_1 ;
或者使用克隆的方式:
create table stocks_seq_2 stored as sequencefile as select * from stocks_1;

查看数据,是乱码,说明是二进制文件

parquetfile 类型

create external table if not exists stocks_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;

使用insert into的方式加载数据
insert into stocks_parquet select * from stocks_1 ;
或者使用克隆的方式:
create table stocks_parquet_1 stored as parquet as select * from stocks_1;

rcfile类型:

create external table if not exists stocks_rcfile (
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 rcfile;

使用insert into的方式加载数据
insert into stocks_rcfile select * from stocks_1;
或者使用克隆的方式:
create table stocks_rcfile_2 stored as rcfile as select * from stocks_1;

orcfile类型:rcfile的升级版

create external table if not exists stocks_orcfile (
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 ','
stored as orcfile;

使用insert into的方式加载数据
insert into stocks_orcfile select * from stocks_1;
或者使用克隆的方式:
create table stocks_orcfile_2 stored as orcfile as select * from stocks_1;

查询速度和压缩比例对比:

select count(*) from stocks_1;
select count(*) from stocks_seq_1;
select count(*) from stocks_parquet;       
select count(*) from stocks_rcfile;
select count(*) from stocks_orcfile;
比较一下上述五个查询所需要的时间

文件存储格式是真正的压缩吗? 每一种文件文件格式有一定的压缩比例,但是不是真正的压缩,而是文件格式带来的。

4、Hive的压缩【是优化手段之一】

hive的压缩使用的是工具压缩,跟存储格式自带压缩不是一回事儿。

HQL语句最终会被编译成Hadoop的Mapreduce job,因此hive的压缩设置,实际上就是对底层MR在处理数据时的压缩设置。

1)hive在map阶段压缩

map阶段的设置, 就是在MapReduce的shuffle阶段对mapper产生的中间结果数据压缩 。 在这个阶段,优先选择一个低CPU开销的算法。因为map阶段要将数据传递给reduce阶段,使用压缩可以提高传输效率。

<!-- 指定要不要开启中间压缩 -->
<property>
    <name>hive.exec.compress.intermediate</name>
    <value>false</value>
</property>

<!-- 指定中间压缩想要使用的压缩编码器(类文件) -->
<property>
    <name>hive.intermediate.compression.codec</name>
    <value/>
</property>

<!-- 指定压缩编码器中的那种压缩类型 -->
<property>
    <name>hive.intermediate.compression.type</name>
    <value/>
</property>

2)hive在reduce阶段的压缩

<!-- 指定要不要开启最终压缩。 -->
<property>
  <name>hive.exec.compress.output</name>
  <value>false</value>
</property>

注意:如果开启,默认使用中间压缩配置的压缩编码器和压缩类型

3)常见的压缩类型

企业中一般使用snappy和lzo进行压缩。

4)压缩编码器

5)实战一下

-- 开启中间压缩机制
hive (yhdb)> set hive.exec.compress.intermediate=true;
-- 设置中间压缩编码器
hive (yhdb)> set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.DefaultCodec;
-- 设置压缩类型
hive (yhdb)> set hive.intermediate.compression.type=RECORD;
-- 开启reduce端的压缩机制
hive (yhdb)> set hive.exec.compress.output=true;
-- 创建表
create external table if not exists stocks_seq_2 (
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 ','
stored as sequencefile;

--动态加载数据:
insert into stocks_seq_2 select * from stocks_1;

使用压缩后:16.71M

使用压缩前:19.37M

压缩工具如何判断好坏? 压缩比例高,解压速度快!

5、视图 view

这个来自于数据库,mysql就有视图。

复习mysql的视图:

类似于虚拟表或者临时表,本身不存储数据。
创建视图的语句:
create view 视图的名字 as  select 语句。

跟虚拟表的区别是:创建了视图,可以反复使用,不会因为你关闭客户端而消失。

创建一个视图:

create view v_emp_dept as
select emp.*,dept.dname,dept.loc from emp join dept on emp.deptno=dept.deptno;

使用视图:

select * from v_emp_dept where deptno=30;

删除视图:

drop view v_emp_dept;

以上是mysql视图的演示,hive也支持视图:

create view if not exists v_1 as select * from t_user  ;

show tables; 

show create table v_1; 
desc v_1;

drop view if exists v_1;

hive 高版本的不支持索引了,所以使用 datagrip 的时候,hive.log 中会出现大量的错误。大概是 show index.... 错误

第五题:
有如下数据,表示1、2、3三名学生选修了a、b、c、d、e、f中的若干课程
id  course
1   a
1   b
1   c
1   e
2   a
2   c
2   d
2   f
3   a
3   b
3   c
3   e
根据如上数据,查询出如下结果,其中1表示选修,0表示未选修
id  a  b  c  d  e  f
1   1  1  1  0  1  0
2   1  0  1  1  0  1
3   1  1  1  0  1  0

SQL:
--第一种方法
select id,
       sum(case when course='a' then 1 else 0 end ) a,
       sum(case when course='b' then 1 else 0 end ) b,
       sum(case when course='c' then 1 else 0 end ) c,
       sum(case when course='d' then 1 else 0 end ) d,
       sum(case when course='e' then 1 else 0 end ) e,
       sum(case when course='f' then 1 else 0 end ) f
       from zhoukao03 group by id;
--第二种方法
select id,
       if(array_contains(collect_set(course),'a'),1,0) a,
       if(array_contains(collect_set(course),'b'),1,0) b,
       if(array_contains(collect_set(course),'c'),1,0) c,
       if(array_contains(collect_set(course),'d'),1,0) d,
       if(array_contains(collect_set(course),'e'),1,0) e,
       if(array_contains(collect_set(course),'f'),1,0) f
       from courses group by id;

假如查询出如下结果

id     a        b          c         d            e            f
1   选修  选修      选修   未选修    选修      未选修
2   选修  未选修  选修    选修      未选修   选修
3   选修  选修     选修    未选修    选修      未选修


create  table courses (
id  int,
course string
)
row format delimited
fields terminated by '\t';
 
load data local inpath '/home/hivedata/zuoye5.txt' into table courses;
 
select id,
       if(array_contains(collect_set(course),'a'),'选修','未选修') a,
       if(array_contains(collect_set(course),'b'),'选修','未选修') b,
       if(array_contains(collect_set(course),'c'),'选修','未选修') c,
       if(array_contains(collect_set(course),'d'),'选修','未选修') d,
       if(array_contains(collect_set(course),'e'),'选修','未选修') e,
       if(array_contains(collect_set(course),'f'),'选修','未选修') f
       from courses group by id;