Hive建表(二) 分区,分桶,动态分区数量不够怎么办?

分区(partition)
分区主要用于提高性能,一张表在重新划分区域形成新的文件夹(如性比分成男和女),查找的时候根据性别的男和女,就可以先过滤掉不用的数据,从而不用再从开始一个个去查,从而提高查询性能;
分区又分为静态分区和动态分区
静态分区:
静态分区就是自己手动创建分区目录,插入的时候必须首先要知道有什么分区类型,而且每个分区都要写一个load data加载本地文件,所以当我们在插入数据的时候指定分区,其实就是新建一个目录或者子目录,或者在原有的目录上添加数据文件。静态分区的列是在编译时期,通过用户传递来决定。
建表时定义静态分区用 partitioned by 举例
create table employee_ partitioned(建表时定义分区
name string,
work_ place ARRAY< string>,
skills_ score MAP<string,int>,
depart_ title MAP<string,ARRAY< string>> )
通过PARTITIONED BY定义分区
partitioned by (gender string)
row format delimited
fields terminated by ‘,’
collection items terminated by ‘,’
map keys terminated by ‘:’
stored as textfile;
上篇文章已经具体说明每个字段作用,这里就不详述;这里就根据gender定义了一个分区;创建分区的时候有时也会报个错,这个错和我上篇文章一样是字符集的问题,解决方法也有说过,看过的都可以解决。
load data加载本地文件我也说过,加载时设置分区名,到hdfs上查看会发现,表下面有创建目录的子目录gender=xxx(分区名),最后在分区名下存放实际的数据文件(load加载进表的文件)。
当然也可以建表后在添加分区:
alter table employee
partitioned add partition (gender=‘male’) partition(gender=‘female’);
删除分区
alter table employee_ partitioned drop partition (gender=‘male’) partition(gender=‘female’);

动态分区
动态分区却不是手动自定义的,而是系统分配的;
动态分区是通过数据来进行判断;详细来说,动态分区只有在SQL执行时才能决定。
想要使用动态分区就必须先设置属性才行:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

动态分区设置方法 insert overwrite
insert overwrite table userinfos partition (year, month)
select userid, username , age, gender, regexp_ replace(birthday,’/’,’-’) as birthday, split(birt,’/’)[0] as year, split (birthday,’/’)[1] as month from customs limit 3;
根据年月来动态分组 ,根据分割单独拿到年和月的值
由于是系统进行分组,当数据量大的时候会有一种情况出现,发现系统的分区数量不足,会报一个错

解决办法:要重新设置分区数量
set hive.exec.max.dynamic.partitions.pernode=600000;
set hive.exec.max.dynamic.partitions=6000000;
set hive.exec.max.create.files=6000000;

再运行就好了!

动态分桶
说的通俗点,就是当数据量大时,对数据进行分组抽样,取其中一部分值比较;就好比超市的物品数量太多,对某一批次的某些物品进行抽样检查,如果合格,也就代表这些批次都是合格的。
分桶对应HDFS中的文件,使抽样(sampling)更高效;根据“桶列”的哈希函数将数据进行分桶,并且分桶只有动态分桶;
设置动态分桶
set hive.enforce.bucketing = true;
定义分桶
clustered by (列名) into 4 buckets
对哪列分桶,分几桶,桶数最好是2的n次方
注意
必须使用INSERT方式加载数据

分桶抽样(sampling)
随机抽样基于整行数据
select * from table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON rand()) s;
bucket 3抽第三桶的 桶数为分子 / 32 为分母 分桶取名s rand() 随机
意思就是 :随机抽取第三桶的32分之几
随机抽样基于指定列(使用分桶列更高效)
select * from table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON 列名) s;
随机抽样基于block size

每个桶取10%
select * from table_name TABLESAMPLE(10 PERCENT) s;

取1M的数据进行抽样
select * from table_name TABLESAMPLE(1M) s;

取10行进行抽样
select * from table_name TABLESAMPLE(10 rows) s;

猜你喜欢

转载自blog.csdn.net/zp17834994071/article/details/106694785