如何将列添加到现有的hive分区表?

时间:2016-11-14 05:29:33

标签: hive

alter table abc add columns (stats1 map<string,string>, stats2 map<string,string>)

我用上面的查询改变了我的表格。但是在检查数据之后,我得到了两个额外列的NULL。我没有收到数据。

screenshot

4 个答案:

答案 0 :(得分:2)

要将列添加到分区表中,您需要重新创建分区。 假设表是外部的,并且数据文件已包含新列,请执行以下操作: 1.更改表添加列... 2.重新创建分区。对于每个分区,请执行Drop然后创建。新创建的分区模式将继承表模式。

或者,您可以删除表,然后创建表并创建所有分区,或者只需运行MSCK REPAIR TABLE abc命令即可​​恢复它们。 Amazon Elastic MapReduce(EMR)的Hive版本上的等效命令是:ALTER TABLE table_name RECOVER PARTITIONS。 请参阅此处的手册:RECOVER PARTITIONS

同样在Hive 1.1.0及更高版本中,您可以使用CASCADE的{​​{1}}选项。请参阅此处的手册:ADD COLUMN

这些建议适用于外部表格。

答案 1 :(得分:2)

CASCADE是解决方案。

查询:

ALTER TABLE dbname.table_name ADD columns (column1 string,column2 string) CASCADE; 

这会更改表格元数据的列,并将相同的更改级联到所有分区元数据。 RESTRICT是默认设置,仅限列更改表元数据。

答案 2 :(得分:0)

正如其他人所指出的,CASCADE将更改所有分区的元数据。如果没有CASCADE,则要更改旧分区以包括新列,则需要先DROP个旧分区,然后再填充它们,INSERT OVERWRITE不带{{1} }无效,因为元数据不会更新为新的默认元数据。

比方说,您已经无意中运行了DROP而没有alter table abc add columns (stats1 map<string,string>, stats2 map<string,string>),然后您CASCADE了一个旧分区而没有先删除。数据将存储在基础文件中,但是如果您从蜂巢中查询该分区的表,该数据将不会显示,因为元数据没有更新。可以解决此问题,而不必使用以下命令重新运行插入覆盖:

  1. 运行INSERT OVERWRITE并复制添加新列之前存在的所有列定义
  2. 运行SHOW CREATE TABLE dbname.tblname
  3. 运行ALTER TABLE dbname.tblname REPLACE COLUMNS ({paste in col defs besides columns to add here}) CASCADE
  4. 很高兴所有分区的元数据都已更改=)

作为第2-3步的示例:

ALTER TABLE dbname.tblname ADD COLUMNS (newcol1 int COMMENT "new col") CASCADE

答案 3 :(得分:0)

仅当您的数据已分区并且您知道最新分区的位置时,此解决方案才有效。在这种情况下,您可以执行以下操作,而不是执行恢复分区或修复这是一项昂贵的操作:

  • 读取分区表并获取架构详细信息
  • 阅读要更新的表
  • 现在找到所有不同的列,并为每个列做一个修改表

发布scala代码以供参考:

def updateMetastoreColumns(spark: SparkSession, partitionedTablePath: String, toUpdateTableName: String): Unit = {
    //fetch all column names along with their corresponding datatypes from latest partition
    val partitionedTable = spark.read.orc(partitionedTablePath)
    val partitionedTableColumns = partitionedTable.columns zip partitionedTable.schema.map(_.dataType.catalogString)

    //fetch all column names along with their corresponding datatypes from currentTable
    val toUpdateTable = spark.read.table(toUpdateTableName)
    val toUpdateTableColumns = toUpdateTable.columns zip toUpdateTable.schema.map(_.dataType.catalogString)

    //check if new columns are present in newer partition
    val diffColumns = partitionedTableColumns.diff(toUpdateTableColumns)

    //update the metastore with new column info
    diffColumns.foreach {column: (String, String) => {
      spark.sql(s"ALTER TABLE ${toUpdateTableName} ADD COLUMNS (${column._1} ${column._2})")
    }}
  }

这将帮助您动态查找添加到较新分区中的最新列,并动态地将其更新到您的metastore。