如何使用 sqoop 在 hive 中创建多级分区

Posted

技术标签:

【中文标题】如何使用 sqoop 在 hive 中创建多级分区【英文标题】:how to create multi level partition in hive using sqoop 【发布时间】:2016-08-15 07:21:53 【问题描述】:

我需要使用 Sqoop 创建具有三个分区年/月/日的配置单元表。我在 sqoop 中检查了 --hive-partition-key--hive-partition-value。使用这些参数,我创建了这样的分区 year --hive-partition-key year --hive-partition-value '2016' 我的问题是如何为分区键和分区值传递多个值来创建像年/月/日这样的分区。

sqoop import --connect jdbc:postgresql://localhost:7432/test_db \
  --driver org.postgresql.Driver --username pgadmin --password pgadmin@1234 \
  --table user1  \
  --fields-terminated-by '\001' \
  --lines-terminated-by '\012' \
  --hcatalog-database test \
  --hcatalog-table user1 \
  --hcatalog-partition-keys year,month,day \
  --hcatalog-partition-values '2016,08,15' \
  --verbose
ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: NoSuchObjectException(message:test.user1 table not found)
        at org.apache.hive.hcatalog.mapreduce.HCatInputFormat.setInput(HCatInputFormat.java:97)
        at org.apache.hive.hcatalog.mapreduce.HCatInputFormat.setInput(HCatInputFormat.java:51)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.configureHCat(SqoopHCatUtilities.java:343)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.configureImportOutputFormat(SqoopHCatUtilities.java:783)
        at org.apache.sqoop.mapreduce.ImportJobBase.configureOutputFormat(ImportJobBase.java:98)
        at org.apache.sqoop.mapreduce.ImportJobBase.runImport(ImportJobBase.java:259)
        at org.apache.sqoop.manager.SqlManager.importTable(SqlManager.java:673)
        at org.apache.sqoop.tool.ImportTool.importTable(ImportTool.java:497)
        at org.apache.sqoop.tool.ImportTool.run(ImportTool.java:605)
        at org.apache.sqoop.Sqoop.run(Sqoop.java:143)
        at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
        at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:179)
        at org.apache.sqoop.Sqoop.runTool(Sqoop.java:218)
        at org.apache.sqoop.Sqoop.runTool(Sqoop.java:227)
        at org.apache.sqoop.Sqoop.main(Sqoop.java:236)
Caused by: NoSuchObjectException(message:test.user1 table not found)
        at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$get_table_result$get_table_resultStandardScheme.read(ThriftHiveMetastore.java:34980)
        at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$get_table_result$get_table_resultStandardScheme.read(ThriftHiveMetastore.java:34948)
        at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$get_table_result.read(ThriftHiveMetastore.java:34879)
        at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78)
        at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$Client.recv_get_table(ThriftHiveMetastore.java:1214)
        at org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore$Client.get_table(ThriftHiveMetastore.java:1200)
        at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.getTable(HiveMetaStoreClient.java:1201)
        at org.apache.hive.hcatalog.common.HCatUtil.getTable(HCatUtil.java:180)
        at org.apache.hive.hcatalog.mapreduce.InitializeInput.getInputJobInfo(InitializeInput.java:105)
        at org.apache.hive.hcatalog.mapreduce.InitializeInput.setInput(InitializeInput.java:86)
        at org.apache.hive.hcatalog.mapreduce.HCatInputFormat.setInput(HCatInputFormat.java:95)
        ... 14 more

更新命令:

sqoop import --connect jdbc:postgresql://localhost:7432/test_db \
  --driver org.postgresql.Driver --username pgadmin --password pgadmin@1234 \
  --table user1  \
  --create-hcatalog-table \
  --hcatalog-table user1 \
  --hcatalog-partition-keys year,month,day \
  --hcatalog-partition-values '2016,08,15' \
  --verbose

更新命令后出错

16/08/17 05:53:20 INFO hcat.SqoopHCatUtilities: Executing external HCatalog CLI process with args :-f,/tmp/hcat-script-1471413200625
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities: MismatchedTokenException(10!=288)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.antlr.runtime.BaseRecognizer.recoverFromMismatchedToken(BaseRecognizer.java:617)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:115)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.primitiveType(HiveParser.java:39530)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.type(HiveParser.java:38772)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.colType(HiveParser.java:38522)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.columnNameType(HiveParser.java:38222)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.columnNameTypeList(HiveParser.java:36445)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.hive.ql.parse.HiveParser.createTableStatement(HiveParser.java:4864)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities:         at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
16/08/17 05:53:24 INFO hcat.SqoopHCatUtilities: FAILED: ParseException line 3:15 mismatched input ',' expecting ( near 'varchar' in primitive type specificat
16/08/17 05:53:25 DEBUG util.ClassLoaderStack: Restoring classloader: sun.misc.Launcher$AppClassLoader@326de728
16/08/17 05:53:25 ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: HCat exited with status 64
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.executeExternalHCatProgram(SqoopHCatUtilities.java:1129)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.launchHCatCli(SqoopHCatUtilities.java:1078)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.createHCatTable(SqoopHCatUtilities.java:625)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.configureHCat(SqoopHCatUtilities.java:340)
        at org.apache.sqoop.mapreduce.hcat.SqoopHCatUtilities.configureImportOutputFormat(SqoopHCatUtilities.java:783)
        at org.apache.sqoop.mapreduce.ImportJobBase.configureOutputFormat(ImportJobBase.java:98)
        at org.apache.sqoop.mapreduce.ImportJobBase.runImport(ImportJobBase.java:259)
        at org.apache.sqoop.manager.SqlManager.importTable(SqlManager.java:673)
        at org.apache.sqoop.tool.ImportTool.importTable(ImportTool.java:497)
        at org.apache.sqoop.tool.ImportTool.run(ImportTool.java:605)
        at org.apache.sqoop.Sqoop.run(Sqoop.java:143)
        at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
        at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:179)
        at org.apache.sqoop.Sqoop.runTool(Sqoop.java:218)
        at org.apache.sqoop.Sqoop.runTool(Sqoop.java:227)
        at org.apache.sqoop.Sqoop.main(Sqoop.java:236)

【问题讨论】:

因为你有硬编码的分区值,比如 2016,08,15 如何编码,以防我有动态分区? @Mahebub 【参考方案1】:

为了使用 Sqoop 将数据导入到多键分区的 Hive 表中,您可以使用 hcatalog-table feature

例如,在你的情况下,你可以使用这样的东西:

(...) --hcatalog-table <your_table_name> --hcatalog-partition-keys year,month,day
 --hcatalog-partition-values 2016,07,01

根据documentation:

这两个选项用于指定多个静态分区 键/值对。在以前的版本中,--hive-partition-key 和 --hive-partition-value 选项用于指定静态分区键/值对,但只有一级静态分区键 可以提供。选项 --hcatalog-partition-keys 和 --hcatalog-partition-values 允许提供多个键和值作为静态分区键。多个选项值是 用 ,(逗号)分隔。例如,如果 hive 分区键为 要导出/导入的表是用分区键名称定义的 年、月、日以及年=1999 的特定分区, month=12, day=31 是所需的分区,然后是两者的值 选项如下:

--hcatalog-partition-keys 年、月、日 --hcatalog-partition-values 1999,12,31

【讨论】:

我试过了,但我收到错误原因:NoSuchObjectException(message:default.user1 table not found) 你用什么来启动 sqoop 导入? Oozie? 数据库名称是test还是test_db?在您使用第二个的 URL 中,在您使用第一个的 hcatalog-database 中。 在 postgresql 数据库名称是 test_db。在导入到 hdfs 时,我正在更改数据库的名称。它适用于配置单元导入。对于 hcatalog,我尝试使用相同的数据库名称,但问题仍然相同。 您能在 Sqoop 命令中添加选项--create-hcatalog-table 吗?默认情况下,HCatalog 表假定存在于 Sqoop 中。【参考方案2】:

我们需要在步骤中实现这一点。在这个更新的命令中:标记上面你正在做两件事。

创建新表和 sqooping 数据,根据我的观察,这一次是行不通的,因为我们必须使用 sqoop 创建多级分区。

所以首先create just create ddl using hcatalogue 来支持多级分区..

第 1 步:

sqoop import \
--connect jdbc:oracle:thin \
--username xxxx \
--password yyyy \
--query  'select EMPNO,ENAME,MGR,HIREDATE,SAL,COMM from  t_test_emp  where  $CONDITIONS AND 1=2' \
--create-hcatalog-table \
--hcatalog-database db1 \
--hcatalog-table test_part1 \
--hcatalog-partition-keys  DEPTNO,JOB \
--hcatalog-partition-values  1,1 \
-m 1

第 2 步: 现在插入数据:

sqoop import \
--connect jdbc:oracle:thin:  \
--username xxxx  \
--password yyyy \
--table t_test_emp \
--columns EMPNO,DEPTNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM \
--hcatalog-database db1 \
--hcatalog-table test_part1 \
-m 1

它会起作用的..

【讨论】:

它是否也适用于动态多键分区? @swapnil 帕蒂尔 多键是什么意思?我们这里已经有多键,即 DEPTNO,JOB 这一行是做什么的 --hcatalog-partition-values 1,1 ?它是基于dept = 1和job = 1的硬编码值进行分区吗?如果我的表有多个 dept 值,例如 1,2..10 并且我想为每个 dept 值创建分区怎么办。对于每个部门分区,我想添加子分区... 在第 1 步 :dept=1 和 job=1 仅用于创建分区表结构,如果您看到 --query 子句我们正在执行 $CONDITIONS AND 1=2 即不导入任何数据。在第 2 步:我们正在执行实际导入(分区没有硬编码)

以上是关于如何使用 sqoop 在 hive 中创建多级分区的主要内容,如果未能解决你的问题,请参考以下文章

在 hive 的外部表中创建分区

大数据--sqoop数据导入导出

hive中创建外部分区表使用location是指定数据存放位置还是指数据来源

我们可以像在 Hive 中一样在 Big Query 中创建动态分区吗?

hive中创建外部分区表测试

我想使用 sqoop 导入作业将数据 sqoop 到 hive 列分区表中。我们应该怎么做?