Hive之分区(Partitions)和桶(Buckets)

转自:http://www.aahyhaa.com/archives/316

hive引入partition和bucket的概念,中文翻译分别为分区和桶(我觉的不是很合适,但是网上基本都是这么翻译,暂时用这个吧),这两个概念都是把数据划分成块,分区是粗粒度的划分桶是细粒度的划分,这样做为了可以让查询发生在小范围的数据上以提高效率。

首先介绍分区的概念,还是先来个例子看下如果创建分区表:
[code lang=”sql”]
create table logs_partition(ts bigint,line string) –ts timestamp line 每一行日志
partitioned by (dt string,country string) — 分区列 dt 日志产生日期
[/code]
创建分区表需要在定义表的时候声明分区列,这个分区列是个比较有意思的东西下面来看看,向表中导入数据:
[code lang=”sql”]
load data local inpath ‘input/hive/partitions/file1′
into table logs_partition
partition(dt=’2001-01-01′,country=’GB’);
…….
— 看下表的结构
hive> desc logs_partition;
OK
ts bigint None
line string None
dt string None
country string None

# Partition Information
# col_name data_type comment

dt string None
country string None
Time taken: 0.265 seconds, Fetched: 10 row(s)

查看一个表的所有分区
hive> show partitions logs_partition;
OK
dt=2001-01-01/country=GB
dt=2001-01-01/country=US
dt=2001-01-02/country=GB
dt=2001-01-02/country=US
Time taken: 0.186 seconds, Fetched: 4 row(s)

[/code]
导入完数据后看下hive数据仓库表logs_partition下的文件目录结构
/user/hive/warehouse/logs_partition

看到了吧分区列都成了目录了,这样查询的时候就会定位到某个目录下而大大提高了查询效率,在查看表结构的时候分区列跟其他列并无区别,看个查询语句:
[code lang=”sql”]
SELECT ts, dt, line
FROM logs
WHERE country=’GB’;

1 2001-01-01 Log line 1
2 2001-01-01 Log line 2
4 2001-01-02 Log line 4
Time taken: 36.316 seconds, Fetched: 3 row(s)

[/code]
这个查询只会查询file1, file2, file4这三个文件还有一个有趣的问题就是,查看下数据文件fieldX
里面都只包含两列ts和line并不包含dt和country这两个分区列,但是从查询结果看分区列和非分区列并无差别,实际上分区列都是从数据仓库的分区目录名得来的。

接下来说说桶,桶是更为细粒度的数据范围划分,它能使一些特定的查询效率更高,比如对于具有相同的桶划分并且jion的列刚好就是在桶里的连接查询,还有就是示例数据,对于一个庞大的数据集我们经常需要拿出来一小部分作为样例,然后在样例上验证我们的查询,优化我们的程序。

下面看看如何创建带桶的表
[code lang=”sql”]
create table bucket_user (id int,name string)
clustered by (id) into 4 buckets;
[/code]
关键字clustered声明划分桶的列和桶的个数,这里以用户的id来划分桶,划分4个桶。
以下为了简便划分桶的列简称为桶列
hive会计算桶列的hash值再以桶的个数取模来计算某条记录属于那个桶

向这种带桶的表里面导入数据有两种方式,一种是外部生成的数据导入到桶表,一种是利用hive来帮助你生成桶表数据
由于hive在load数据的时候不能检查数据文件的格式与桶的定义是否匹配,如果不匹配在查询的时候就会报错,所以最好还是让hive来帮你生成数据,简单来说就是利用现有的表的数据导入到新定义的带有桶的表中,下面来看看:
已经存在的表:
[code lang=”bash”]
hive> select * from users;
OK
0 Nat
2 Joe
3 Kay
4 Ann

hive> set hive.enforce.bucketing=true –必须设置这个数据,hive才会按照你设置的桶的个数去生成数据
[/code]

下面把user的数据导入到bucketed_users中
[code language=”lang=‘sql”]
insert overwrite table bucketed-users
select * from users;
[/code]
然后见证奇迹的时刻:
[code lang=”bash”]
hive> dfs -ls /user/hive/warehouse/bucketed_users;
-rw-r–r– 1 root supergroup 12 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000000_0
-rw-r–r– 1 root supergroup 0 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000001_0
-rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000002_0
-rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000003_0

hive> dfs -cat /user/hive/warehouse/bucketed_users/000000_0;
0Nat
4Ann

[/code]

下面来看看利用bucket来对示例数据进行查询
[code lang=”sql”]
—带桶的表
select * from bucketed_users
tablesample(bucket 1 out of 4 on id);

—不带桶的表
select * from users
tablesample(bucket 1 out of 4 on rand());

[/code]
tablesample的作用就是让查询发生在一部分桶上而不是整个数据集上,上面就是查询4个桶里面第一个桶的数据
相对与不带桶的表这无疑是效率很高的,因为同样都是需要一小部分数据,但是不带桶的表需要使用rand()函数,需要在整个数据集上检索。

时间: 05-24

Hive之分区(Partitions)和桶(Buckets)的相关文章

HIVE—索引、分区和分桶的区别

一.索引 简介 Hive支持索引,但是Hive的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键. Hive索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少MapReduce任务中需要读取的数据块的数量. 为什么要创建索引? Hive的索引目的是提高Hive表指定列的查询速度.没有索引时,类似'WHERE tab1.col1 = 10' 的查询,Hive会加载整张表或分区,然后处理所有的rows,但是如果在字段col1上面存在索引时,那么只会加载和处理文件的一部分

hive归档分区

归档hive历史分区不会减少hdfs存储空间,但是可以有效减轻hadoop namenode的压力,尤其在于小文件比较多的情况下. $mkdir $HIVE_HOME/auxlib $ cp /opt/cdh-5.3.6/hadoop-2.5.0/share/hadoop/tools/lib/hadoop-archives-2.5.0-cdh5.3.6.jar /opt/cdh-5.3.6/hive-0.13.1/auxlib/hadoop-archives-2.5.0-cdh5.3.6.jar

【解决】hive动态添加partitions不能超过100的问题

Author: kwu [解决]hive动态添加partitions不能超过100的问题,全量动态生成partitions超过100会出现例如以下异常: The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode. Maximum was set to: 100 解决100限制,可设置例

Hive表的分区与分桶

1.Hive分区表 Hive使用select语句进行查询的时候一般会扫描整个表内容,会消耗很多时间做没必要的工作.Hive可以在创建表的时候指定分区空间,这样在做查询的时候就可以很好的提高查询的效率. 创建分区表的语法: [java] view plain copy create table tablename( name string )partitioned by(key,type...); 示例 [java] view plain copy drop table if exists emp

Hive里的分区和分桶再谈

 分桶是细粒度的,分桶是不同的文件. 分区是粗粒度的,即相当于,表下建立文件夹.分区是不同的文件夹. 桶在对指定列进行哈希计算时,会根据哈希值切分数据,使每个桶对应一个文件. 里面的id是哈希值,分过来的. 分桶,一般用作数据倾斜和数据抽样方面.由此,可看出是细粒度. Hive 中创建分区表没有什么复杂的分区类型(范围分区.列表分区.hash 分区,混合分区等).分区列也不是表中的一个实际的字段,而是一个或者多个伪列.意思是说,在表的数据文件中实际并不保存分区列的信息与数据. 注意:普通表(外部

Hive动态分区

Hive默认是静态分区,我们在插入数据的时候要手动设置分区,如果源数据量很大的时候,那么针对一个分区就要写一个insert,比如说,我们有很多日志数据,我们要按日期作为分区字段,在插入数据的时候我们不可能手动的去添加分区,那样太麻烦了.还好,Hive提供了动态分区,动态分区简化了我们插入数据时的繁琐操作. 使用动态分区的时候必须开启动态分区(动态分区默认是关闭的),语句如下: [java] view plain copy set hive.exec.hynamic.partition=true;

Hive 桶的分区

(一).桶的概念: 对于每一个表(table)或者分区, Hive可以进一步组织成桶(没有分区能分桶吗?),也就是说桶是更为细粒度的数据范围划分.Hive也是 针对某一列进行桶的组织.Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中. 把表(或者分区)组织成桶(Bucket)有两个理由:(1).获得更高的查询处理效率.桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构.具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接

Hive桶表

桶(bucket)是指将表或分区中指定列的值为key进行hash,hash到指定的桶中,这样可以支持高效采样工作. 抽样(sampling)可以在全体数据上进行采样,这样效率自然就低,它还是要去访问所有数据.而如果一个表已经对某一列制作了bucket,就可以采样所有桶中指定序号的某个桶,这就减少了访问量. 针对桶的操作,总共有四步: 1).开启桶的服务 Hive > set hive.enforce.buketing=true; 2).创建桶表 首先,我们来看如何告诉Hive—个表应该被划分成桶

Hive学习之动态分区及HQL

Hive动态分区 1.首先创建一个分区表create table t10(name string) partitioned by(dt string,value string)row format delimited fields terminatedby '\t' lines terminated by '\n'stored as textfile;2.然后对hive进行设置,使之支持动态分区,set hive.exec.dynamic.partition.mode=nonstrict;如果限