Hive 分区字段限制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive 分区字段限制相关的知识,希望对你有一定的参考价值。

参考技术A hivesql分区字段不可以有中文,否则会报错如下:

Failed with exception MetaException(message:javax.jdo.JDOException: Exception thrown when executing query : SELECT DISTINCT 'org.apache.hadoop.hive.metastore.model.MPartition' AS NUCLEUS_TYPE , A0 . CREATE_TIME , A0 . LAST_ACCESS_TIME , A0 . PART_NAME , A0 . PART_ID FROM PARTITIONS A0 LEFT OUTER JOIN TBLS B0 ON A0 . TBL_ID = B0 . TBL_ID LEFT OUTER JOIN DBS C0 ON B0 . DB_ID = C0 . DB_ID WHERE B0 . TBL_NAME = ? AND C0 . NAME = ? AND A0 . PART_NAME = ?
at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:677)
at org.datanucleus.api.jdo.JDOQuery.executeInternal(JDOQuery.java:388)
at org.datanucleus.api.jdo.JDOQuery.execute(JDOQuery.java:252)
at org.apache.hadoop.hive.metastore.ObjectStore.getMPartition(ObjectStore.java:1607)
at org.apache.hadoop.hive.metastore.ObjectStore.getPartitionWithAuth(ObjectStore.java:1875)
at org.apache.hadoop.hive.metastore.ObjectStoreWithBIMapping.getPartitionWithAuth(ObjectStoreWithBIMapping.java:341)
at org.apache.sentry.binding.hive.v2.metastore.AuthorizingObjectStoreV2WithBIMapping.getPartitionWithAuth(AuthorizingObjectStoreV2WithBIMapping.java:218)
at org.apache.sentry.binding.hive.v2.metastore.MTAuthorizingObjectStoreV2WithBIMapping.getPartitionWithAuth(MTAuthorizingObjectStoreV2WithBIMapping.java:231)
at sun.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.hive.metastore.RawStoreProxy.invoke(RawStoreProxy.java:114)
at com.sun.proxy.$Proxy11.getPartitionWithAuth(Unknown Source)
at org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.get_partition_with_auth(HiveMetaStore.java:3311)
at sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.hive.metastore.RetryingHMSHandler.invoke(RetryingHMSHandler.java:107)
at com.sun.proxy.$Proxy13.get_partition_with_auth(Unknown Source)
at sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.hive.metastore.HiveMetaStore$MetricHMSProxy.invoke(HiveMetaStore.java:6752)
at com.sun.proxy.$Proxy13.get_partition_with_auth(Unknown Source)
at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$Processor$get_partition_with_auth.getResult(ThriftHiveMetastore.java:9950)
at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$Processor$get_partition_with_auth.getResult(ThriftHiveMetastore.java:9934)
at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:39)
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39)
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge$Server$TUGIAssumingProcessor$1.run(HadoopThriftAuthBridge.java:747)
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge$Server$TUGIAssumingProcessor$1.run(HadoopThriftAuthBridge.java:742)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1690)
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge$Server$TUGIAssumingProcessor.process(HadoopThriftAuthBridge.java:742)
at org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:286)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
NestedThrowablesStackTrace:
java.sql.SQLException: Illegal mix of collations (latin1_bin,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation '='
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)

hive 分区表

参考技术A hive 分区表:

分区字段的物理表现:

hive分区表 ,其真实的表现其实就是在 存储hive表的文件夹的下面,创建新的文件夹,

文件夹的名字是 分区字段=字段取值 这种格式的。

分区的优点:

当分区表的数据很大的时候,可以指定查询表格之中的部分数据。

设置表格分区字段需要的注意点:

1:分区字段的取值不要很多,因为这样会造成表的文件夹的下面会出现很多的小的文件夹

2: 一般可以将sql之中 where 之中出现的字段作为 分区的字段。(可以当作分区字段选取的一个参考)

查看表格是否是分区表:

desc formatted table_name

分区表的话 ,会有Partition Information

向分区表插入数据:

情况分为:

1:向表格之中插入数据,明确指定插入的分区的名字

2:向表格之中插入数据,不明确指定插入的数据的名字,而是根据插入的数据的某个字段的取值来自动决定数据

被插入到哪一个分区之中。被称为动态分区。

如何开启hive 动态分区的功能?

set  hive.exec.dynamici.partition=true;

hive 动态分区:有两种模式:

严格模式 和非严格模式

严格模式:

动态分区的时候,必须有一个分区是静态的。

非严格模式,对分区是否是静态的不在意。

如何设置 动态分区的模式?

set hive.exec.dynamic.partition.mode=nostrict

默认的模式是strict 严格模式。

插入数据时 明确指定需要插入的分区的值:

sql demo :

1:load data [local] inpath 'path' into table xxx partition(partition_fields partiton_type)

2:insert into table table_a partition(partition_fields partition_type)

select * from table_b [....];

使用insert 的时候 ,需要注意前后表的表的字段数目是匹配的,

如果表的前后字段是不匹配的话,那么就是会报错。

向分区表之中插入数据的时候,根据数据的某个字段的值,来创建分区,

以及决定数据被插入到哪一个分区之中。

sql demo:

对一个分区 进行动态分区:

首先要设置两个参数:

set  hive.exec.dynamici.partition=true;

set hive.exec.dynamic.partition.mode=nostrict

然后就是可以使用动态分区了。

分区值的推断,是根据后面查询的最后字段来决定的,只有一个分区,

那么就是查询的最后一个字段,如果是两个,那么就是从后往前的字段进行匹配。

insert into table pp partition(`date`) select name,age,`date` from par;

这里的sql demo 

是将par 的`date` 字段 作为pp表之中 `date`分区的取值。

部分动态分区:

就是多个分区,但是前面的分区的取值是取静态的,然后后面的分区的取值是未定的。

类似于 partition(country='china',city)

这里需要注意的是顺序,静态分区在前面,动态分区在后面。

然后就是多个分区,完全的动态分区:

完全动态分区的时候,就是使用后面select 查询的表进行分区数据的匹配。



动态分区在实际使用的时候会遇到的问题:

动态分区的一个使用场景:

首先加载数据到一个表格a之中,然后将这个表格之中再次转化到另外一个

表格b之中,表a转化到表b的时候,使用动态分区。

因为直接使用load 加载数据的时候,对于分区表而言,加载数据只能指定固定的分区名,

无法使用动态分区来加载数据。

相应的问题就是:

如果a表本身含有很多的文件,那么使用动态分区的时候,

那么在b表的时候,就是会产生很多的小文件。

原因如下:

如果 a表之中数据文件是200个,

那么动态分区的时候,可能会产生200个map,

然后一个map包含的数据之中,可能有多个分区的取值,

所以一个map 会产生多个文件。

所以后果就是,在新的b表之中的每个分区下面,会产生很多的小文件。

总结来说:不好的影响就是可能会产生很多的小文件。

解决的方式:

因为动态分区转化成为的mapredue job 是没有reduce,所以数目不好控制,

所以可以采用的方式,就是手动增加reduce的数目,

可以使用distributed by 来增加 reduce的数目。

insert into table table_a partition('partition_name')

select *  from table_b

dirtribute by partitoin_name

但是这样的方式,就是可能导致 reduce之间包含的数据量的不均匀。

所以解决的方法就是:

distribute by rand()

使用hash 随机分区,这样的方式,来讲数据均匀分配到reduce之中。

然后每个reduce 会产生 分区取值数目的文件,

例子: reduce数目为 200 分区的取值数位24

那么最后产生的文件的数目就是 200* 24个文件。

其实可以通过exlpain 来解析sql的执行计划,这样的话,

可以看出是否具有reduce操作。

查询表的分区信息:

show partitions table_name

向分区表之中增加分区:

alter table table_name add partition(pfield=pvalue,...)

如果表格之中有多个分区的话,那么增加分区的时候,也是多个分区

一同增加的。

删除分区:

alter table table_name drop partition(pfield=pval)

分区信息修改:

分区信息的修改分为 分区名的修改 和 分区数据的修改 两种

分区名的修改

alter table table_name partition(pfield=pvalue) rename to partition(pfield=pvalue)

分区数据的修改:

alter table table_name partition(pfield=pvalue) set location 'data_location'

以上是关于Hive 分区字段限制的主要内容,如果未能解决你的问题,请参考以下文章

hive的严格模式和分区

Hive 限制中的最大动态分区

hive表新增字段后,新字段无法写入的问题 -- cascade

Hive分区的作用

Hive 中分析查询的限制

Hive的严格模式