本文大部份内容转至:http://blog.csdn.net/u010330043/article/details/51277868node
Hive 的分区经过在建立表时启动 PARTITION BY 实现,用来分区的维度并非实际数据的某一列,具体分区的标志是由插入内容时给定的。当要查询某一分区的内容时能够采用 WHERE 语句, 例如使用 “WHERE tablename.partition_key>a” 建立含分区的表。建立分区语法以下。mysql
CREATE TABLE table_name( ... ) PARTITION BY (dt STRING,country STRING)
一、 建立分区sql
Hive 中建立分区表没有什么复杂的分区类型(范围分区、列表分区、hash 分区,混合分区等)。分区列也不是表中的一个实际的字段,而是一个或者多个伪列。意思是说,在表的数据文件中实际并不保存分区列的信息与数据。 数据库
- 须要注意,Partitioned by子句中的列定义是表中正式的列,称为“分区列”partition column。
- 可是,数据文件并不包含这些列的值,由于他们源于目录名。
建立一个简单的分区表。oop
hive> 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 两个字段做为分区列。一般状况下须要预先建立好分区,而后才能使用该分区。例如:spa
hive> alter table partition_test add partition (stat_date='2016-04-28',province='beijing');
这样就建立了一个分区。这时会看到 Hive 在HDFS 存储中建立了一个相应的文件夹。.net
$ hadoop fs -ls /user/hive/warehouse/partition_test/stat_date=2015-01-18 /user/hive/warehouse/partition_test/stat_date=2016-04-28/province=beijing ----显示刚刚建立的分区
每个分区都会有一个独立的文件夹,在这个例子中stat_date是主层次,province是副层次,code
全部stat_date='20150118',而province不一样的分区都会在orm
/user/hive/warehouse/partition_test/stat_date=20110728 下面,
而stat_date不一样的分区都会在blog
/user/hive/warehouse/partition_test/ 下面;
如:$ hadoop fs -ls /user/hive/warehouse/partition_test/ Found 2 items drwxr-xr-x - admin supergroup 0 2015-01-28 19:46 /user/hive/warehouse/partition_test/stat_date=20150126 drwxr-xr-x - admin supergroup 0 2015-01-29 09:53 /user/hive/warehouse/partition_test/stat_date=20150128
注意,由于分区列的值要转化为文件夹的存储路径,因此若是分区列的值中包含特殊值,如 '%', ':', '/', '#',它将会被使用%加上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 2015-01-29 10:06 /user/hive/warehouse/partition_test/stat_date=2015/01/28 drwxr-xr-x - admin supergroup 0 2015-01-26 19:46 /user/hive/warehouse/partition_test/stat_date=20150129 drwxr-xr-x - admin supergroup 0 2016-01-29 09:53 /user/hive/warehouse/partition_test/stat_date=20150128
二、 插入数据;
使用一个辅助的非分区表 partition_test_input 准备向 partition_test 中插入数据,实现步骤以下。
1) 查看 partition_test_input 表的结构和数据,命令以下:
hive> desc partition_test_input; -- 表结构 hive> select * from partition_test_input; -- 表数据
2)向 partition_test 的分区中插入数据,命令以下:
insert overwrite table partition_test partition(stat_date='2015-01-18',province='jiangsu') select member_id,name from partition_test_input where stat_date='2016-04-28' and province='jiangsu';
向多个分区插入数据,命令以下。
hive> from partition_test_input insert overwrite table partition_test partition(stat_date='2016-04-28',province='jiangsu') select member_id,name from partition_test_input where stat_date='2016-04-28' and province='jiangsu' insert overwrite table partition_test partition(stat_date='2016-04-28',province='sichuan') select member_id,name from partition_test_input where stat_date='2016-04-28' and province='sichuan' insert overwrite table partition_test partition(stat_date='2016-04-28',province='beijing') select member_id,name from partition_test_input where stat_date='2016-04-28' and province='beijing';
特别要注意,在其余数据库中,通常向分区表中插入数据时系统会校验数据是否符合该分区,若是不符合会报错。而在hive中,向某个分区中插入什么样的数据彻底是由人来控制的,由于分区键是伪列,不实际存储在文件中,如:
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
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都变成相同的了,由于这两列的数据是根据文件夹的名字读取来的,而不是实际从数据文件中读取来的
三、 动态分区
按照上面的方法向分区表中插入数据,若是数据源很大,针对一个分区就要写一个 insert ,很是麻烦。使用动态分区能够很好地解决上述问题。动态分区能够根据查询获得的数据自动匹配到相应的分区中去。
动态分区能够经过下面的设置来打开:
set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict;
动态分区的使用方法很简单,假设向 stat_date=’2016-04-28’ 这个分区下插入数据,至于 province 插到哪一个子分区下让数据库本身来判断。stat_date 叫作静态分区列,province 叫作动态分区列。
hive> insert overwrite table partition_test partition(stat_date='2016-04-28',province) select member_id,name province from partition_test_input where stat_date='2016-04-28';
注意,动态分区不容许主分区采用动态列而副分区采用静态列,这样将致使全部的主分区都要建立副分区静态列所定义的分区。
hive.exec.max.dynamic.partitions.pernode: 每个 MapReduce Job 容许建立的分区的最大数量,若是超过这个数量就会报错(默认值100)。 hive.exec.max.dynamic.partitions:一个 dml 语句容许建立的全部分区的最大数量(默认值100)。 hive.exec.max.created.files:全部 MapReduce Job 容许建立的文件的最大数量(默认值10000)。
尽可能让分区列的值相同的数据在同一个 MapReduce 中,这样每个 MapReduce 能够尽可能少地产生新的文件夹,能够经过 DISTRIBUTE BY 将分区列值相同的数据放到一块儿,命令以下。
insert overwrite table partition_test partition(stat_date,province) select memeber_id,name,stat_date,province from partition_test_input distribute by stat_date,province;