Hive & Impala 中内置有对 Avro,Parquet 文件格式支持。在存储的过程中,也可以使用压缩编码器对数据进行压缩。
- Hive 常用文件格式: http://www.cnblogs.com/Richardzhu/p/3613661.html
- RCFile 介绍(翻译于 《Programing Hive》) :http://flyingdutchman.iteye.com/blog/1871025
- Hive 中的数据压缩(翻译于 《Programing Hive》):http://flyingdutchman.iteye.com/blog/1870878
Hive 中的常见数据格式的存储及压缩格式可以参考以上链接,以下将着重介绍 如何在 Hive 中使用Avro, Parquet 数据格式,以及使用 Snappy 压缩方法对数据进行压缩。
1 Avro 格式:Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
Hive 0.9.1 版本新绑定 Avro SerDe (序列化器/反序列化器的简称),它允许 Hive 从表中读取数据和写回表.
Hive Versions
|
Avro Version
|
---|---|
Hive 0.9.1 | Avro 1.5.3 |
Hive 0.10, 0.11, and 0.12 | Avro 1.7.1 |
Hive 0.13 and 0.14 | Avro 1.7.5 |
你需要将Avro的schema复制到HDFS上, 并创建一个目录包含一些 Avro 股票记录的示例:
$ hadoop fs -put $HIP_HOME/schema schema
$ hadoop fs -mkdir stock_hive
$ hip hip.ch3.avro.AvroStockFileWrite \
--input test-data/stocks.txt \
--output stock_hive/stocks.avro
需要注意的是,以下创建表的格式是 Hive 通用的格式,但是在 Hive 0.14 及以后的版本里,在DDL语句中可以直接使用"STORED AS AVRO" 来指定表为Avro格式。AvroSerDe 会根据 Hive 表的Schema 来创建适合的 Avro Schema。这大大增加了 Avro 在 Hive 中的可用性。
详细请参考:https://cwiki.apache.org/confluence/display/Hive/AvroSerDe
hive>
CREATE
EXTERNAL
TABLE
tweets
> COMMENT
"A table backed by Avro data with the
> Avro schema embedded in the CREATE TABLE statement"
> ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
> STORED
AS
> INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
> OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
> LOCATION
'/user/wyp/examples/input/'
> TBLPROPERTIES (
>
'
avro.schema.literal
'
=
'{
> "type": "record",
> "name": "Tweet",
> "namespace": "com.miguno.avro",
> "fields": [
> { "name":"username", "type":"string"},
> { "name":"tweet", "type":"string"},
> { "name":"timestamp", "type":"long"}
> ]
> }'
> );
Time taken: 0.076 secondshive> describe tweets;OK username string from deserializer tweet string from deserializer timestamp bigint from deserializer
将avro.schema.literal中的 schame 定义存放在一个文件中,比如:twitter.avsc
{
"
type
"
:
"record"
,
"
name
"
:
"Tweet"
,
"
namespace
"
:
"com.miguno.avro"
,
"fields"
: [
{
"name"
:
"username"
,
"type"
:
"string"
},
{
"name"
:
"tweet"
,
"type"
:
"string"
},
{
"name"
:
"timestamp"
,
"type"
:
"long"
}
]
}
-- Create 外部表 tweets
CREATE
EXTERNAL
TABLE
tweets
COMMENT
"A table backed by Avro data with the Avro schema stored in HDFS"
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
STORED
AS
INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
LOCATION
'/user/wyp/examples/input/'
TBLPROPERTIES (
);
-- Create 外部表 stocks
hive>
CREATE
EXTERNAL
TABLE
stocks
COMMENT
"An Avro stocks table"
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
STORED
AS
INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
LOCATION
'/user/YOUR-HDFS-USERNAME/stock_hive/'
TBLPROPERTIES (
);
hive> describe tweets;
OK
username string from deserializer
tweet string from deserializer
timestamp bigint from deserializer
AvroSerDe 实际上支持4种方法来为 Avro Tasble 定义一个 Schema: (详细参考:https://cwiki.apache.org/confluence/display/Hive/AvroSerDe.)
你可以通过 Describe 关键词来查询一个 Hive 表的 Schema :
hive> describe stocks;
symbol string
date
string
open
double
high
double
low
double
close
double
volume
int
adjclose
double
运行一个 query 来确认是否完成了,可以通过如下的 Hive Query Language (HiveQL) 来记录每个股票代码的数量 -- stock symbol:
hive>
SELECT
symbol,
count
(*)
FROM
stocks
GROUP
BY
symbol;
AAPL 10
CSCO 10
GOOG 5
MSFT 10
2 Parquet 格式:
Hive 要求数据已经存在于目录里面,所有你需要创建一个目录 并且将股票的Parquet格式文件复制过去 :
$ hadoop fs -mkdir parquet_avro_stocks $ hadoop fs -cp stocks.parquet parquet_avro_stocks
接下来,您将创建一个Hive外部表并且定义它的模式。如果你不能确定结构模式, 你可以通过以下方法来查看需要处理 Parquet 文件的 Schema 信息(使用 Parquet tools 中的 Schema 命令):
2.1. 使用 Parquet tools 来查看 Parquet文件的 schema 信息:
$ hip -
-nolib
parquet.tools.Main schema stocks.parquet
message hip.ch3.avro.gen.Stock {
required binary symbol (UTF8);
required binary date (UTF8);
required double open;
required double high;
required double low;
required double close;
required int32 volume;
required double adjClose;
}
比如说 Avro, 使用元数据来存储 Avro的Schema,你可以通过以下命令查看输出:
$ hip -
-nolib
parquet.tools.Main meta stocks.parquet
creator: parquet
-mr
(build 3f25ad97f20...)
extra: avro.schema = {
"type"
:
"record"
,
"name"
:
"Stock"
,
"namespace"
...
file schema: hip.ch3.avro.gen.Stock
---------------------------------------------------------------------
symbol: REQUIRED BINARY O:UTF8
R
:0 D:0
date: REQUIRED BINARY O:UTF8
R
:0 D:0
open: REQUIRED DOUBLE
R
:0 D:0
high: REQUIRED DOUBLE
R
:0 D:0
low: REQUIRED DOUBLE
R
:0 D:0
close: REQUIRED DOUBLE
R
:0 D:0
volume: REQUIRED INT32
R
:0 D:0
adjClose: REQUIRED DOUBLE
R
:0 D:0
row
group
1: RC:45 TS:2376
---------------------------------------------------------------------
symbol: BINARY SNAPPY DO:0 FPO:4 SZ:85/84/0.99 VC:45 ENC:PD ...
date: BINARY SNAPPY DO:0 FPO:89 SZ:127/198/1.56 VC:45 ENC ...
open: DOUBLE SNAPPY DO:0 FPO:216 SZ:301/379/1.26 VC:45 EN ...
high: DOUBLE SNAPPY DO:0 FPO:517 SZ:297/379/1.28 VC:45 EN ...
low: DOUBLE SNAPPY DO:0 FPO:814 SZ:292/379/1.30 VC:45 EN ...
close: DOUBLE SNAPPY DO:0 FPO:1106 SZ:299/379/1.27 VC:45 E ...
volume: INT32 SNAPPY DO:0 FPO:1405 SZ:203/199/0.98 VC:45 EN ...
adjClose: DOUBLE SNAPPY DO:0 FPO:1608 SZ:298/379/1.27 VC:45 E ...
2.3.将 Hive 中的数据存储为 Parquet 格式 -- Hive 0.13
hive>
CREATE
EXTERNAL
TABLE
parquet_stocks(
symbol string,
date
string,
open
double
,
high
double
,
low
double
,
close
double
,
volume
int
,
adjClose
double
) STORED
AS
PARQUET
LOCATION
'/user/YOUR_USERNAME/parquet_avro_stocks'
;
hive> select distinct(symbol) from parquet_stocks; AAPL CSCO GOOG MSFT YHOO
You can use the same syntax to create the table in Impala.
3. 使用 Sanppy 压缩编码来将数据写入到新表中 / 或者可以将压缩后的数据文件 copy 到 HDFS 中数据定义目录下面。
3.1 从旧表进行复制数据“:
hive>
SET
hive.
exec
.compress.
output
=
true
;
hive>
SET
avro.
output
.codec =
snappy
;
hive>
CREATE
TABLE
google_stocks
COMMENT
"An Avro stocks table containing just Google stocks"
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.
AvroSerDe
'
STORED
AS
INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
TBLPROPERTIES (
'avro.schema.url'
=
'hdfs:///user/YOUR-USERNAME/schema/stock.avsc'
);
OK
hive>
INSERT
OVERWRITE
TABLE
google_stocks
SELECT
*
FROM
stocks
WHERE
symbol =
'GOOG'
;
OK
读取新表数据:hive>
select
*
from
google_stocks limit 5;
OK
GOOG 2009-01-02 308.6 321.82 305.5 321.32 3610500 321.32
GOOG 2008-01-02 692.87 697.37 677.73 685.19 4306900 685.19
GOOG 2007-01-03 466.0 476.66 461.11 467.59 7706500 467.59
GOOG 2006-01-03 422.52 435.67 418.22 435.23 13121200 435.23
GOOG 2005-01-03 197.4 203.64 195.46 202.71 15844200 202.71
3.2 压缩前我们的数据:
{
"username"
:
"miguno"
,
"tweet"
:
"Rock: Nerf paper, scissors is fine."
,
"timestamp"
: 1366150681
},
{
"username"
:
"BlizzardCS"
,
"tweet"
:
"Works as intended. Terran is IMBA."
,
"timestamp"
: 1366154481
},
{
"username"
:
"DarkTemplar"
,
"tweet"
:
"From the shadows I come!"
,
"timestamp"
: 1366154681
},
{
"username"
:
"VoidRay"
,
"tweet"
:
"Prismatic core online!"
,
"timestamp"
: 1366160000
}
3.3 压缩完的数据假如存放在/home/wyp/twitter.avsc文件中,我们将这个数据复制到HDFS中的/user/wyp/examples/input/目录下:
hadoop fs
-put
/home/wyp/twitter.avro /user/wyp/examples/input/
3.4 读取压缩后的数据:
hive>
select
*
from
tweets limit 5;;
OK
miguno Rock: Nerf paper, scissors
is
fine. 1366150681
BlizzardCS Works
as
intended. Terran
is
IMBA. 1366154481
DarkTemplar
From
the shadows I come! 1366154681
VoidRay Prismatic core online! 1366160000
Time
taken: 0.495 seconds, Fetched: 4 row(s)