Hive_1. 数据存储 & 压缩

来源:互联网 发布:苹果平板看书软件 编辑:程序博客网 时间:2024/05/16 14:54
Hive 常用的数据文件存储格式有: TextFile,SequenceFile,RCFile, ORCFile (0.11以后出现), 这几种格式已经有人详细介绍过,在这里就不做描述了。
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.1Avro 1.5.3Hive 0.10, 0.11, and 0.12Avro 1.7.1Hive 0.13 and 0.14Avro 1.7.5如果需要在Hive中使用Avro,需要在$HIVE_HOME/lib目录下放入以下四个工具包:avro-1.7.1.jar、avro-tools-1.7.4.jar、 jackson-core-asl-1.8.8.jar、jackson-mapper-asl-1.8.8.jar。当然,你也可以把这几个包存在别的路径下面,但是你需要把这四个包放在CLASSPATH中。
你需要将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
AvroStockFileWrite.java         stocks.txt
为了解析Avro格式的数据,我们可以在Hive建表的时候用下面语句:
需要注意的是,以下创建表的格式是 Hive 通用的格式,但是在 Hive 0.14 及以后的版本里,在DDL语句中可以直接使用"STORED AS AVRO" 来指定表为Avro格式。AvroSerDe 会根据 Hive 表的Schema 来创建适合的 Avro Schema。这大大增加了 Avro 在 Hive 中的可用性。
详细请参考:https://cwiki.apache.org/confluence/display/Hive/AvroSerDe
stock.avsc2.1 在定义中指定 schema
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 seconds
hive> describe tweets;
OKusername            string              from deserializer   tweet               string              from deserializer   timestamp           bigint              from deserializer

2.2  调用一个 shema 文件的 URL

将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 (
        'avro.schema.url'='hdfs:///user/wyp/examples/schema/twitter.avsc'
    );
 
-- 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 (
'avro.schema.url'='hdfs:///user/YOUR-HDFS-USERNAME/schema/stock.avsc'
  );

hive> describe tweets;
OKusername            string              from deserializer   tweet               string              from deserializer   timestamp           bigint              from deserializer

AvroSerDe 实际上支持4种方法来为 Avro Tasble 定义一个 Schema: (详细参考:https://cwiki.apache.org/confluence/display/Hive/AvroSerDe.)
  • Use avro.schema.url -- 如上例 2.2
  • Use schema.literal and embed the schema in the create statement
  • Use avro.schema.literal and pass the schema into the script -- 如上例 2.1
  • Use none to ignore either avro.schema.literal or avro.schema.url

你可以通过 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;
}

2.2 Parquet 同样允许对象模型使用元数据来存储反序列化的信息。
比如说 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;AAPLCSCOGOOGMSFTYHOO

You can use the same syntax to create the table in Impala.


3. 使用 Sanppy 压缩编码来将数据写入到新表中  /  或者可以将压缩后的数据文件 copy 到 HDFS 中数据定义目录下面。
如果你希望将数据以 Avro 格式来存储 Hive 表,接下来的例子将会向你展示了 你该如何copy stocks 表的子集并且插入到一张新表中。该例子同时强调了你该如果使用 Snappy 压缩编码来将数据写入到新表中。
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)

0 0
原创粉丝点击