使用HIVE CONCATENATE合并所有分区的Hive操作

4

我有一个外部hive表,该表在源系统上进行了分区,这意味着数据将来自多个源系统。数据目录的结构如下:

/app/hadoop/MyProject/SchemaName/TableName/PartitionColumn=SoruceSystem1

/app/hadoop/MyProject/SchemaName/TableName/PartitionColumn=SoruceSystem2

/app/hadoop/MyProject/SchemaName/TableName/PartitionColumn=SoruceSystem3

...

/app/hadoop/MyProject/SchemaName/TableName/PartitionColumn=SoruceSystemN

所有进入SourceSystem文件夹的数据都是流式数据,因此在每个源系统下我们会得到很多文件 :)

我正在考虑每天合并所有这些文件,例如:将SourceSystem1中的所有文件合并,合并后的文件留在SoruceSystem1文件夹中,对其他文件夹也是这样。

通常情况下:当只有一个文件夹时,可以使用alter table schema.table PARTITION(PartitionColumn={SourceSystemName}) CONCATENATE;正常运行,但我需要同时操作所有文件夹。

解决办法是编写一个shell脚本循环遍历所有分区,并为每个源系统名称重复执行该语句,但我正在寻找一些开箱即用的东西来解决这个问题。

非常感谢您在这里提供的任何帮助。


你需要编写这样一个shell脚本(使用hdfs dfs -ls获取分区,而不是使用Hive describe)。 - Harold
1个回答

7

重要提示 - 如果您的表结构已经发生了变化(例如添加了新列),但仍包含使用旧结构的文件,则CONCATENATE可能会悄悄丢弃这些文件。请参见错误报告。为解决此问题,我们对非托管表进行了故障排除,并在Hive 3.0.0中最终解决了该问题。

现在我们需要分两步进行操作。

首先,我们获取所需表中的分区,并将它们写入一个文本文件,以便稍后可以参考。

beeline --showHeader=false --outputformat=tsv2 --silent=true -e "SHOW PARTITIONS database.table" > found_partitions.txt

这将输出找到的分区列表,不包括标题或框架。
接下来,我们需要遍历分区列表,将潜在的分区分隔符(part1=some/part2=thing)替换为逗号,因为前者不是合法的Hive字符。如果您的表中只有一个分区结构,则此操作无效。我们还假设所有分区都是字符串,并且需要用引号括起来。
#!/bin/bash

for line in `cat found_partitions.txt`; do
    echo "the next partition is $line"
    partition=`(echo $line | sed -e 's/\//,/g' -e "s/=/='/g" -e "s/,/',/g")`\'
    beeline -e "ALTER TABLE database.table PARTITION($partition) CONCATENATE" 
done

注意:您可能需要设置一些配置才能让beeline适用于您。您可能想为此设置一个别名。
 beeline -u "jdbc:hive2://<SERVER>:<PORT>/;serviceDiscoveryMode=<zooKeeper>;zooKeeperNamespace=<hiveserver2>;principal=<USER>;transportMode=<SOMETHING>;httpPath=<SOMETHING>"

1
完美的答案。只有一个小语法错误在你的注释中。 echo语句末尾需要加上双引号。 echo "下一个分区是$line" - Sagar Morakhia
@SagarMorakhia 我没注意到。谢谢,已经修复了。 - kfkhalili

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接