如何将列添加到现有的配置单元分区表中?

ca1c2owp  于 2021-06-28  发布在  Hive
关注(0)|答案(4)|浏览(577)
  1. alter table abc add columns (stats1 map<string,string>, stats2 map<string,string>)

我用上面的问题修改了我的表。但是在检查数据之后,我得到了两个额外列的空值。我没有得到数据。
截图

fumotvh3

fumotvh31#

级联就是解决方案。
查询:

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

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

ou6hu8tu

ou6hu8tu2#

正如其他人所指出的那样 CASCADE 将更改所有分区的元数据。没有 CASCADE ,如果要更改旧分区以包含新列,则需要 DROP 先把旧分区填满, INSERT OVERWRITE 没有 DROP 不会工作,因为元数据不会更新为新的默认元数据。
假设你已经跑了 alter table add columns (stats1 map<string,string>, stats2 map<string,string>) 没有 CASCADE 一个意外然后你 INSERT OVERWRITE 一个没有先掉下来的旧分区。数据将存储在底层文件中,但是如果从配置单元中查询该分区的表,它将不会显示,因为元数据没有更新。无需使用以下方法重新运行insert overwrite即可修复此问题:
SHOW CREATE TABLE dbname.tblname 并复制添加新列之前存在的所有列定义
ALTER TABLE dbname.tblname REPLACE COLUMNS ({paste in col defs besides columns to add here}) CASCADEALTER TABLE dbname.tblname ADD COLUMNS (newcol1 int COMMENT "new col") CASCADE 很高兴所有分区的元数据都已更改()
作为步骤2-3的示例:

  1. DROP TABLE IF EXISTS junk.testcascade ;
  2. CREATE TABLE junk.testcascade (
  3. startcol INT
  4. )
  5. partitioned by (d int)
  6. stored as parquet
  7. ;
  8. INSERT INTO TABLE junk.testcascade PARTITION(d=1)
  9. VALUES
  10. (1),
  11. (2)
  12. ;
  13. INSERT INTO TABLE junk.testcascade PARTITION(d=2)
  14. VALUES
  15. (1),
  16. (2)
  17. ;
  18. SELECT * FROM junk.testcascade ;
  19. +-----------------------+----------------+--+
  20. | testcascade.startcol | testcascade.d |
  21. +-----------------------+----------------+--+
  22. | 1 | 1 |
  23. | 2 | 1 |
  24. | 1 | 2 |
  25. | 2 | 2 |
  26. +-----------------------+----------------+--+
  27. --no cascade! opps
  28. ALTER TABLE junk.testcascade ADD COLUMNS( testcol1 int, testcol2 int) ;
  29. INSERT OVERWRITE TABLE junk.testcascade PARTITION(d=3)
  30. VALUES
  31. (1,1,1),
  32. (2,1,1)
  33. ;
  34. INSERT OVERWRITE TABLE junk.testcascade PARTITION(d=2)
  35. VALUES
  36. (1,1,1),
  37. (2,1,1)
  38. ;
  39. --okay! because we created this table after altering the metadata
  40. select * FROM junk.testcascade where d=3;
  41. +-----------------------+-----------------------+-----------------------+----------------+--+
  42. | testcascade.startcol | testcascade.testcol1 | testcascade.testcol2 | testcascade.d |
  43. +-----------------------+-----------------------+-----------------------+----------------+--+
  44. | 1 | 1 | 1 | 3 |
  45. | 2 | 1 | 1 | 3 |
  46. +-----------------------+-----------------------+-----------------------+----------------+--+
  47. --not okay even tho we inserted =( because the metadata isnt changed
  48. select * FROM junk.testcascade where d=2;
  49. +-----------------------+-----------------------+-----------------------+----------------+--+
  50. | testcascade.startcol | testcascade.testcol1 | testcascade.testcol2 | testcascade.d |
  51. +-----------------------+-----------------------+-----------------------+----------------+--+
  52. | 1 | NULL | NULL | 2 |
  53. | 2 | NULL | NULL | 2 |
  54. +-----------------------+-----------------------+-----------------------+----------------+--+
  55. --cut back to original columns
  56. ALTER TABLE junk.testcascade REPLACE COLUMNS( startcol int) CASCADE;
  57. --add
  58. ALTER table junk.testcascade ADD COLUMNS( testcol1 int, testcol2 int) CASCADE;
  59. --it works!
  60. select * FROM junk.testcascade where d=2;
  61. +-----------------------+-----------------------+-----------------------+----------------+--+
  62. | testcascade.startcol | testcascade.testcol1 | testcascade.testcol2 | testcascade.d |
  63. +-----------------------+-----------------------+-----------------------+----------------+--+
  64. | 1 | 1 | 1 | 2 |
  65. | 2 | 1 | 1 | 2 |
  66. +-----------------------+-----------------------+-----------------------+----------------+--+
展开查看全部
h79rfbju

h79rfbju3#

只有当您的数据被分区并且您知道最新分区的位置时,此解决方案才有效。在这种情况下,您可以执行以下操作,而不是执行代价高昂的恢复分区或修复操作:
读取分区表并获取架构详细信息
读取要更新的表
现在找出哪些列是不同的,并为每个列做一个alter表
发布scala代码以供参考:

  1. def updateMetastoreColumns(spark: SparkSession, partitionedTablePath: String, toUpdateTableName: String): Unit = {
  2. //fetch all column names along with their corresponding datatypes from latest partition
  3. val partitionedTable = spark.read.orc(partitionedTablePath)
  4. val partitionedTableColumns = partitionedTable.columns zip partitionedTable.schema.map(_.dataType.catalogString)
  5. //fetch all column names along with their corresponding datatypes from currentTable
  6. val toUpdateTable = spark.read.table(toUpdateTableName)
  7. val toUpdateTableColumns = toUpdateTable.columns zip toUpdateTable.schema.map(_.dataType.catalogString)
  8. //check if new columns are present in newer partition
  9. val diffColumns = partitionedTableColumns.diff(toUpdateTableColumns)
  10. //update the metastore with new column info
  11. diffColumns.foreach {column: (String, String) => {
  12. spark.sql(s"ALTER TABLE ${toUpdateTableName} ADD COLUMNS (${column._1} ${column._2})")
  13. }}
  14. }

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

展开查看全部
0x6upsns

0x6upsns4#

要将列添加到分区表中,需要重新创建分区。假设表是外部的,并且数据文件已经包含新列,请执行以下操作:1。更改表添加列。。。2.重新创建分区。对于每个分区,先删除然后创建。新创建的分区架构将继承表架构。
或者,您可以删除表,然后创建表并创建所有分区,或者简单地恢复它们 MSCK REPAIR TABLE 命令。amazon elastic mapreduce(emr)版本的hive上的等效命令是: ALTER TABLE table_name RECOVER PARTITIONS . 请参阅此处的手册:恢复分区
在Hive1.1.0及更高版本中,您也可以使用 CASCADE 选择 ALTER TABLE ADD|REPLACE COLUMNS . 请参阅此处的手册:添加列
这些建议适用于外部表。

相关问题