hive的数据存储浅谈

一、导言:

     Hive是基于Hadoop分布式文件系统,它的数据存储在Hadoop分布式文件系统中。Hive本身是没有专门的数据存储格式,也没有为数据建立索引,只需要在创建标的时候告诉Hive数据中的列分隔和行分隔符,Hive就可以解析数据。所以往hive里导入数据只是简单的将数据移动到表所在的目录中;Hive是建立在 Hadoop 上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。Hive 定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。
Hive 没有专门的数据格式。 Hive 可以很好的工作在 Thrift 之上,控制分隔符,也允许用户指定数据格式

二、hive的数据类型

    Hive的数据分为表数据和元数据,表数据是Hive中表格(table)具有的数据;而元数据是用来存储表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。下面分别来介绍。

三、hive数据存储

Hive是基于Hadoop分布式文件系统的,它的数据存储在Hadoop分布式文件系统中。

1、表:Hive中的表和关系型数据库中的表在概念上很类似,每个表在HDFS中都有相应的目录用来存储表的数据,这个目录可以通过${HIVE_HOME}/conf/hive-site.xml配置文件中的 hive.metastore.warehouse.dir属性来配置,这个属性默认的值是/user/hive/warehouse(这个目录在 HDFS上),我们可以根据实际的情况来修改这个配置。如果我有一个表wyp,那么在HDFS中会创建/user/hive/warehouse/wyp 目录(这里假定hive.metastore.warehouse.dir配置为/user/hive/warehouse);wyp表所有的数据都存放在这个目录中。这个例外是外部表。

2、外部表:Hive中的外部表和表很类似,但是其数据不是放在自己表所属的目录中,而是存放到别处,这样的好处是如果你要删除这个外部表,该外部表所指向的数据是不会被删除的,它只会删除外部表对应的元数据;而如果你要删除表,该表对应的所有数据包括元数据都会被删除。

3、分区:在Hive中,表的每一个分区对应表下的相应目录,所有分区的数据都是存储在对应的目录中。比如wyp 表有dt和city两个分区,则对应dt=20131218,city=BJ对应表的目录为/user/hive/warehouse /dt=20131218/city=BJ,所有属于这个分区的数据都存放在这个目录中。

4、桶:对指定的列计算其hash,根据hash值切分数据,目的是为了并行,每一个桶对应一个文件(注意和分区的区别)。比如将wyp表id列分散至16个桶中,首先对id列的值计算hash,对应hash值为0和16的数据存储的HDFS目录为:/user /hive/warehouse/wyp/part-00000;而hash值为2的数据存储的HDFS 目录为:/user/hive/warehouse/wyp/part-00002。

盗个图:


表是在数据库下面,而表里面又要分区、桶、倾斜的数据和正常的数据等;分区下面也是可以建立桶的。

四、Hive的元数据

Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。 由于Hive的元数据需要不断的更新、修改,而HDFS系统中的文件是多读少改的,这显然不能将Hive的元数据存储在HDFS中。而是存放在传统的RDBMS中,典型的如mysql,derby等,这里我们以mysql为元数据库。可以通过以下配置来修改Hive元数据的存储方式。

<property> 
  <name>javax.jdo.option.ConnectionURL</name> 
  <value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8 
                    &createDatabaseIfNotExist=true</value> 
  <description>JDBC connect string for a JDBC metastore</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionDriverName</name> 
  <value>com.mysql.jdbc.Driver</value> 
  <description>Driver class name for a JDBC metastore</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionUserName</name> 
  <value>root</value> 
  <description>username to use against metastore database</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionPassword</name> 
  <value>123456</value> 
  <description>password to use against metastore database</description> 
</property> 
你还需要将相应数据库的启动复制到${HIVE_HOME}/lib目录中,这样才能将元数据存储在对应的数据库中。

五、Hive的存储和解析

这部分详情可以参见官方文档:点击打开链接

1.CREATE TABLE

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
  [(col_name data_type [COMMENT col_comment], ...)]
  [COMMENT table_comment]
  [PARTITIONED BY (col_name data_type
    [COMMENT col_comment], ...)]
  [CLUSTERED BY (col_name, col_name, ...)
  [SORTED BY (col_name [ASC|DESC], ...)]
  INTO num_buckets BUCKETS]
  [ROW FORMAT row_format]
  [STORED AS file_format]
  [LOCATION hdfs_path]
CREATE TABLE 创建一个指定名字的表。如果系统名字的表已经存在,则操作异常;用户可以使用 IF NOT EXIST选项来忽略这个异常。

EXTERNAL创建外部表

example1:

我们先来看下hive中如何建表,并通过分析建表语句了解hive中数据的存储解析方式

create table tutorial ( 
    name string,                          --string类型字段name
    number int,	                          -- int类型字段number
    resource array<string>,                    -- string数组类型字段
    detail map<string, int>)                  -- 字典类型(key为字符串,value为整型)
partitioned by (dt string)                      -- 按dt分区,dt类型为string
row format delimited fields terminated by '\t'	      -- 指定列分隔符为tab
collection items terminated by ','	        	-- 指定数组中字段分隔符为逗号
map keys terminated by ':' ;	            	-- 指定字典中KV分隔符为冒号
根据上面的建表语句,对应的数据应该长这样:

balabala2 222 str1,str2,str3 a:1,b:2,c:3

balabala3 333 str4,str5,str6 d:4,e:5,f:6
....
hive在读取数据时,首先根据TAB对列进行分隔,得到name, number, source, detail,name和number不用继续处理,可直接使用

source和detail属于复杂数据类型,hive需要再次进行解析:根据逗号分隔source,detail,再根据冒号分隔detail中每一项的key和value

ps. 这其中涉及到一个概念:读时模式 和 写时模式

读时模式:加载数据时进行数据检验(hive)

写时模式:写入数据时对照模式进行检查(传统RDBMS)

2.hive的几种文件存储格式

hive文件存储格式包括以下几类:
TEXTFILE
SEQUENCEFILE
RCFILE
自定义格式

1.TEXTFILE

默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
example2:
> create table test1(str STRING)  
> STORED AS TEXTFILE;   
OK  
Time taken: 0.786 seconds  
#写脚本生成一个随机字符串文件,导入文件:  
> LOAD DATA LOCAL INPATH '/home/work/data/test.txt' INTO TABLE test1;  
Copying data from file:/home/work/data/test.txt  
Copying file: file:/home/work/data/test.txt  
Loading data to table default.test1  
OK  
Time taken: 0.243 seconds 

2.SEQUENCEFILE

SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点。SequenceFile支持三种压缩选择:NONE, RECORD, BLOCK。 Record压缩率低,一般建议使用BLOCK压缩。


> create table test3(str STRING)  
> STORED AS RCFILE;  
OK  
Time taken: 0.184 seconds  
>  INSERT OVERWRITE TABLE test3 SELECT * FROM test1;

3.自定义格式

当用户的数据文件格式不能被当前 Hive 所识别的时候,可以自定义文件格式。用户可以通过实现inputformat和outputformat来自定义输入输出格式,参考代码:
.\hive-0.8.1\src\contrib\src\java\org\apache\hadoop\hive\contrib\fileformat\base64
example4:
> create table test4(str STRING)  
> stored as  
> inputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat'  
> outputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextOutputFormat'; 
$ cat test1.txt 
aGVsbG8saGl2ZQ==
aGVsbG8sd29ybGQ=
aGVsbG8saGFkb29w
test1文件为base64编码后的内容,decode后数据为:
hello,hive
hello,world
hello,hadoop
load数据并查询:
hive> LOAD DATA LOCAL INPATH '/home/work/test1.txt' INTO TABLE test4;   
Copying data from file:/home/work/test1.txt  
Copying file: file:/home/work/test1.txt  
Loading data to table default.test4  
OK  
Time taken: 4.742 seconds  
hive> select * from test4;  
OK  
hello,hive  
hello,world  
hello,hadoop  
Time taken: 1.953 seconds
相比TEXTFILE和SEQUENCEFILE,RCFILE由于列式存储方式,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE相比其余两种格式具有较明显的优势。


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值