Programming Hive 读书笔记

第九章 模式设计

9.1按天划分的表

hive> CREATE TABLE supply_2011_01_02 (id int, part string, quantity int);
hive> CREATE TABLE supply_2011_01_03 (id int, part string, quantity int);
hive> CREATE TABLE supply_2011_01_04 (id int, part string, quantity int);

hive> .... load data ...

hive> SELECT part,quantity supply_2011_01_02
> UNION ALL
> SELECT part,quantity from supply_2011_01_03
> WHERE quantity < 4;

对于这种情况,应该使用分区表。

hive> CREATE TABLE supply (id int, part string, quantity int)
> PARTITIONED BY (int day);

hive> ALTER TABLE supply add PARTITION (day=20110102);
hive> ALTER TABLE supply add PARTITION (day=20110103);
hive> ALTER TABLE supply add PARTITION (day=20110102);

hive> .... load data ...

hive> SELECT part,quantity FROM supply
> WHERE day>=20110102 AND day<20110103 AND quantity < 4;

9.2 关于分区

hive> CREATE TABLE weblogs (url string, time long )
> PARTITIONED BY (day int, state string, city string);
hive> SELECT * FROM weblogs WHERE day=20110102;
hive> CREATE TABLE weblogs (url string, time long, state string, city string )
> PARTITIONED BY (day int);
hive> SELECT * FROM weblogs WHERE day=20110102;

对上述语句使用两个级别的分区。

hive> CREATE TABLE weblogs (url string, time long, city string )
> PARTITIONED BY (day int, state string);
hive> SELECT * FROM weblogs WHERE day=20110102;

9.3 唯一建和标准化

Hive没有主键或基于序列密钥生成自增键的概念。

9.4 同一份数据多种处理

hive> INSERT OVERWRITE TABLE sales
> SELECT * FROM history WHERE action='purchased';

hive> INSERT OVERWRITE TABLE credits
> SELECT * FROM history WHERE action='returned';

以上语句表达的意思是从源表history读取数据,然后导入到2个不同的表中。然而这种写法,虽然语法正确,但执行效率底下。可使用下面的查询达到同样的目的,且只扫描一次history表。如:

hive> FROM history
> INSERT OVERWRITE sales SELECT * WHERE action='purchased'
> INSERT OVERWRITE credits SELECT * WHERE action='returned';

9.5 对于每个表的分区

9.6 分桶表数据存储

分区是一种提供隔离数据和优化查询的方式。

分桶是将数据集分解成更容易管理的若干部分的一种技术。

hive> CREATE TABLE weblog (url STRING, source_ip STRING)
> PARTITIONED BY (dt STRING, user_id INT);
hive> FROM raw_weblog
> INSERT OVERWRITE TABLE page_view PARTITION(dt='2012-06-08', user_id)
> SELECT server_name, url, source_ip, dt, user_id;
hive> CREATE TABLE weblog (user_id INT, url STRING, source_ip STRING)
> PARTITIONED BY (dt STRING)
> CLUSTERED BY (user_id) INTO 96 BUCKETS;

在使用NSERT … TABLE语句时,需要设置hive.enforce.bucketing属性为目标表的分桶初始化过程设置正确的reducer个数。如:

hive> SET hive.enforce.bucketing = true;
hive> FROM raw_logs
> INSERT OVERWRITE TABLE weblog
> PARTITION (dt='2009-02-25')
> SELECT user_id, url, source_ip WHERE dt='2009-02-25';

若没有设置hive.enforce.bucketing属性,就需要设置和分桶个数相匹配的reducer个数。如set mapred.reduce.tasks=96,在INSERT语句中,在SELECT语句后增加CLUSTER BY语句。

9.7 为表增加列

Hive使用SerDe用于从输入中提取数据。也可以用于输出数据。

使用ALTER TABLE ADD COLUMN语句添加新字段。如:

hive> ALTER TABLE weblogs ADD COLUMNS (user_id string);

无法在现有字段前和中间增加新字段。

9.8 使用列存储表

Hive通常使用行式存储。不过也提供了一个列式SerDe来以混合列式格式存储信息。

9.8.1 重复数据

有足够多的行。如:

state        uid        age
NY        Bob        40
NJ        Sara        32
NY        Peter        14
NY        Sandra        4

9.8.2 多列

state        uid        age        server        tz        many_more …
NY        Bob        40        web1        est        stuff
NJ        Sara        32        web1        est        stuff
NY        Peter        14        web3        pst        stuff
NY        Sandra        4        web45        pst        stuff
hive> SELECT distinct(state) from weblogs;
NY
NJ

基于列式存储。使得表分析数据更快。

9.9 总是使用压缩