所介绍内容基本上是翻译官方文档,比较肤浅,如有错误,请指正!

hive中创建分区表没有什么复杂的分区类型(范围分区、列表分区、hash分区、混合分区等)。分区列也不是表中的一个实际的字段,而是一个或者多个伪列。意思是说在表的数据文件中实际上并不保存分区列的信息与数据。

下面的语句创建了一个简单的分区表:



create table partition_test

(member_id string,

name string

)

partitioned by (

stat_date string,

province string)

row format delimited fields terminated by ',';



这个例子中创建了stat_date和province两个字段作为分区列。通常情况下需要先预先创建好分区,然后才能使用该分区,例如:



alter table partition_test add partition (stat_date='20110728',province='zhejiang');



这样就创建好了一个分区。这时我们会看到hive在HDFS存储中创建了一个相应的文件夹:



$ hadoop fs -ls /user/hive/warehouse/partition_test/stat_date=20110728

Found 1 items

drwxr-xr-x - admin supergroup 0 2011-07-29 09:53 /user/hive/warehouse/partition_test/stat_date=20110728/province=zhejiang



每一个分区都会有一个独立的文件夹,下面是该分区所有的数据文件。在这个例子中stat_date是主层次,province是副层次,所有stat_date='20110728',而province不同的分区都会在/user/hive/warehouse/partition_test/stat_date=20110728 下面,而stat_date不同的分区都会在/user/hive/warehouse/partition_test/ 下面,如:



$ hadoop fs -ls /user/hive/warehouse/partition_test/

Found 2 items

drwxr-xr-x - admin supergroup 0 2011-07-28 19:46 /user/hive/warehouse/partition_test/stat_date=20110526

drwxr-xr-x - admin supergroup 0 2011-07-29 09:53 /user/hive/warehouse/partition_test/stat_date=20110728



注意,因为分区列的值要转化为文件夹的存储路径,所以如果分区列的值中包含特殊值,如 '%', ':', '/', '#',它将会被使用%加上2字节的ASCII码进行转义,如:



hive> alter table partition_test add partition (stat_date='2011/07/28',province='zhejiang');

OK

Time taken: 4.644 seconds



$hadoop fs -ls /user/hive/warehouse/partition_test/

Found 3 items

drwxr-xr-x - admin supergroup 0 2011-07-29 10:06 /user/hive/warehouse/partition_test/stat_date=2011%2F07%2F28

drwxr-xr-x - admin supergroup 0 2011-07-28 19:46 /user/hive/warehouse/partition_test/stat_date=20110526

drwxr-xr-x - admin supergroup 0 2011-07-29 09:53 /user/hive/warehouse/partition_test/stat_date=20110728



我使用一个辅助的非分区表partition_test_input准备向partition_test中插入数据:



hive> desc partition_test_input;

OK

stat_date string

member_id string

name string

province string



hive> select * from partition_test_input;

OK

20110526 1 liujiannan liaoning

20110526 2 wangchaoqun hubei

20110728 3 xuhongxing sichuan

20110728 4 zhudaoyong henan

20110728 5 zhouchengyu heilongjiang



然后我向partition_test的分区中插入数据:



hive> insert overwrite table partition_test partition(stat_date='20110728',province='henan') select member_id,name from partition_test_input where stat_date='20110728' and province='henan';

Total MapReduce jobs = 2

...

1 Rows loaded to partition_test

OK



还可以同时向多个分区插入数据,0.7版本以后不存在的分区会自动创建,0.6之前的版本官方文档上说必须要预先创建好分区:



hive>

> from partition_test_input

> insert overwrite table partition_test partition (stat_date='20110526',province='liaoning')

> select member_id,name where stat_date='20110526' and province='liaoning'

> insert overwrite table partition_test partition (stat_date='20110728',province='sichuan')

> select member_id,name where stat_date='20110728' and province='sichuan'

> insert overwrite table partition_test partition (stat_date='20110728',province='heilongjiang')

> select member_id,name where stat_date='20110728' and province='heilongjiang';

Total MapReduce jobs = 4

...

3 Rows loaded to partition_test

OK



特别要注意,在其他数据库中,一般向分区表中插入数据时系统会校验数据是否符合该分区,如果不符合会报错。而在hive中,向某个分区中插入什么样的数据完全是由人来控制的,因为分区键是伪列,不实际存储在文件中,如:





hive> insert overwrite table partition_test partition(stat_date='20110527',province='liaoning') select member_id,name from partition_test_input;

Total MapReduce jobs = 2

...

5 Rows loaded to partition_test

OK



hive> select * from partition_test where stat_date='20110527' and province='liaoning';

OK

1 liujiannan 20110527 liaoning

2 wangchaoqun 20110527 liaoning

3 xuhongxing 20110527 liaoning

4 zhudaoyong 20110527 liaoning

5 zhouchengyu 20110527 liaoning



可以看到在partition_test_input中的5条数据有着不同的stat_date和province,但是在插入到partition(stat_date='20110527',province='liaoning')这个分区后,5条数据的stat_date和province都变成相同的了,因为这两列的数据是根据文件夹的名字读取来的,而不是实际从数据文件中读取来的:



$ hadoop fs -cat /user/hive/warehouse/partition_test/stat_date=20110527/province=liaoning/000000_0

1,liujiannan

2,wangchaoqun

3,xuhongxing

4,zhudaoyong

5,zhouchengyu



下面介绍一下动态分区,因为按照上面的方法向分区表中插入数据,如果源数据量很大,那么针对一个分区就要写一个insert,非常麻烦。况且在之前的版本中,必须先手动创建好所有的分区后才能插入,这就更麻烦了,你必须先要知道源数据中都有什么样的数据才能创建分区。

使用动态分区可以很好的解决上述问题。动态分区可以根据查询得到的数据自动匹配到相应的分区中去。 

使用动态分区要先设置hive.exec.dynamic.partition参数值为true,默认值为false,即不允许使用:



hive> set hive.exec.dynamic.partition;

hive.exec.dynamic.partition=false

hive> set hive.exec.dynamic.partition=true;

hive> set hive.exec.dynamic.partition;

hive.exec.dynamic.partition=true



动态分区的使用方法很简单,假设我想向stat_date='20110728'这个分区下面插入数据,至于province插入到哪个子分区下面让数据库自己来判断,那可以这样写:



hive> insert overwrite table partition_test partition(stat_date='20110728',province)

> select member_id,name,province from partition_test_input where stat_date='20110728';

Total MapReduce jobs = 2

...

3 Rows loaded to partition_test

OK



stat_date叫做静态分区列,province叫做动态分区列。select子句中需要把动态分区列按照分区的顺序写出来,静态分区列不用写出来。这样stat_date='20110728'的所有数据,会根据province的不同分别插入到/user/hive/warehouse/partition_test/stat_date=20110728/下面的不同的子文件夹下,如果源数据对应的province子分区不存在,则会自动创建,非常方便,而且避免了人工控制插入数据与分区的映射关系存在的潜在风险。



注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区:



hive> insert overwrite table partition_test partition(stat_date,province='liaoning')

> select member_id,name,province from partition_test_input where province='liaoning';

FAILED: Error in semantic analysis: Line 1:48 Dynamic partition cannot be the parent of a static partition 'liaoning'



动态分区可以允许所有的分区列都是动态分区列,但是要首先设置一个参数hive.exec.dynamic.partition.mode :



hive> set hive.exec.dynamic.partition.mode;

hive.exec.dynamic.partition.mode=strict



它的默认值是strick,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。

所以我们要设置:

hive> set hive.exec.dynamic.partition.mode=nostrick;



再介绍3个参数:

hive.exec.max.dynamic.partitions.pernode (缺省值100):每一个mapreduce job允许创建的分区的最大数量,如果超过了这个数量就会报错

hive.exec.max.dynamic.partitions (缺省值1000):一个dml语句允许创建的所有分区的最大数量

hive.exec.max.created.files (缺省值100000):所有的mapreduce job允许创建的文件的最大数量



当源表数据量很大时,单独一个mapreduce job中生成的数据在分区列上可能很分散,举个简单的例子,比如下面的表要用3个map:

1

1

1

2

2

2

3

3

3



如果数据这样分布,那每个mapreduce只需要创建1个分区就可以了: 

         |1

map1 --> |1 

         |1 



         |2

map2 --> |2 

         |2 



         |3

map3 --> |3 

         |3

但是如果数据按下面这样分布,那第一个mapreduce就要创建3个分区: 



         |1

map1 --> |2 

         |3 



         |1

map2 --> |2 

         |3 



         |1

map3 --> |2 

         |3



下面给出了一个报错的例子:

hive> set hive.exec.max.dynamic.partitions.pernode=4;

hive> insert overwrite table partition_test partition(stat_date,province)

> select member_id,name,stat_date,province from partition_test_input distribute by stat_date,province;

Total MapReduce jobs = 1

...

[Fatal Error] Operator FS_4 (id=4): Number of dynamic partitions exceeded hive.exec.max.dynamic.partitions.pernode.. Killing the job.

Ended Job = job_201107251641_0083 with errors

FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.MapRedTask



为了让分区列的值相同的数据尽量在同一个mapreduce中,这样每一个mapreduce可以尽量少的产生新的文件夹,可以借助distribute by的功能,将分区列值相同的数据放到一起:



hive> insert overwrite table partition_test partition(stat_date,province)

> select member_id,name,stat_date,province from partition_test_input distribute by stat_date,province;

Total MapReduce jobs = 1

...

18 Rows loaded to partition_test

OK



好了,关于hive的分区表先简单介绍到这里,后续版本如果有功能的更新我也会再更新。

hive中简单介绍分区表的更多相关文章

  1. hive中简单介绍分区表(partition table)——动态分区(dynamic partition)、静态分区(static partition)

    一.基本概念 hive中分区表分为:范围分区.列表分区.hash分区.混合分区等. 分区列:分区列不是表中的一个实际的字段,而是一个或者多个伪列.翻译一下是:“在表的数据文件中实际上并不保存分区列的信 ...

  2. hive 中简单的udf函数编写

    .注册函数,使用using jar方式在hdfs上引用udf库. $hive.注销函数,只需要删除mysql的hive数据记录即可. delete from func_ru ; delete from ...

  3. hive中导入json格式的数据(hive分区表)

    hive中建立外部分区表,外部数据格式是json的如何导入呢? json格式的数据表不必含有分区字段,只需要在hdfs目录结构中体现出分区就可以了 This is all according to t ...

  4. Hive中的三种不同的数据导出方式介绍

    问题导读:1.导出本地文件系统和hdfs文件系统区别是什么?2.带有local命令是指导出本地还是hdfs文件系统?3.hive中,使用的insert与传统数据库insert的区别是什么?4.导出数据 ...

  5. 计算机启动过程的简单介绍 计算机启动流程 计算机BIOS作用 POST 开机自检 计算机启动顺序 分区表 操作系统启动

    原文地址:4.计算机启动过程的简单介绍 计算机启动流程 计算机BIOS作用 POST 开机自检 计算机启动顺序 分区表 操作系统启动 计算机的启动

  6. [原创]关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  7. 简单介绍一下R中的几种统计分布及常用模型

    统计学上分布有很多,在R中基本都有描述.因能力有限,我们就挑选几个常用的.比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示. 统计分布每一种分布有四个函数:d――density(密度函数) ...

  8. 决策树简单介绍(二) Accord.Net中决策树的实现和使用

    决策树介绍 决策树是一类机器学习算法,可以实现对数据集的分类.预测等.具体请阅读我另一篇博客(http://www.cnblogs.com/twocold/p/5424517.html). Accor ...

  9. Qt中利用QTime类来控制时间,这里简单介绍一下QTime的成员函数的用法:

    Qt中利用QTime类来控制时间,这里简单介绍一下QTime的成员函数的用法: ------------------------------------------------------------ ...

随机推荐

  1. iOS 中的加密方式

    iOS 中的加密方式 1 加密方式主要有: Base64,MD5,RSA,DES,AES,钥匙串存储,Cookie 2 各加密方式的比较 2.1 Base64 2.1.1 基本原理:采用64个基本的 ...

  2. HTML超出文本显示省略号...[text-overflow]

    需要对div或者span同时应用Css: text-overflow:ellipsis; white-space:nowrap; overflow:hidden; 即可实现所想要得到的溢出文本显示省略 ...

  3. vim 使用记录

    编辑 Ctrl + x         数字减1 Ctrl + a         数字加1 di +  {char}    Delete Inner Character  # di": & ...

  4. 页面modal服务

    /** * * * 初始化: * var oneModal = modalSvc.createModal(templateUrl, controller, size); * size可以是:lg或sm ...

  5. 剑指Offer03 逆序输出链表&链表逆序

    多写了个逆序链表 /************************************************************************* > File Name: ...

  6. 递归小Demo

    public class demo5 { public static void main(String[] args) {        //初始值为100         int n = 100;  ...

  7. MongoDB - The mongo Shell, mongo Shell Quick Reference

    mongo Shell Command History You can retrieve previous commands issued in the mongo shell with the up ...

  8. MongoDB - The mongo Shell, Configure the mongo Shell

    Customize the Prompt You may modify the content of the prompt by setting the variable prompt in the  ...

  9. js实现全屏

    详细内容请点击 1.window.open方式 第一种: 在已经打开的一个普通网页上,点击“全屏显示”,然后进入该网页对应的全屏模式.方法为:在网页的<body>与</body> ...

  10. 初见,Devexpress

    [绥江一百]http://www.sj100.net                                                  欢迎,进入绥江一百感谢点击[我的小网站,请大家多 ...