【问题标题】:How to truncate data and drop all partitions from a Hive table using Spark如何使用 Spark 截断数据并从 Hive 表中删除所有分区
【发布时间】:2019-10-06 18:01:13
【问题描述】:

如何使用Spark 2.3.0Hive 表中删除所有数据并删除所有分区

truncate table my_table; // Deletes all data, but keeps partitions in metastore

alter table my_table drop partition(p_col > 0) // does not work from spark

唯一对我有用的是遍历show partitions my_table,将/ 替换为,,然后分别删除每个分区。但必须有更清洁的方法。如果分区列的类型为string,它甚至不起作用。有什么建议吗?

【问题讨论】:

  • 你为什么投反对票?这个问题有答案吗?

标签: apache-spark hive apache-spark-sql hiveql


【解决方案1】:

让我们使用 Spark 2.4.3 设置问题:

// We create the table
spark.sql("CREATE TABLE IF NOT EXISTS potato (size INT) PARTITIONED BY (hour STRING)")

// Enable dynamic partitioning 
spark.conf.set("hive.exec.dynamic.partition.mode","nonstrict")

// Insert some dummy records
(1 to 9).map(i => spark.sql(s"INSERT INTO potato VALUES ($i, '2020-06-07T0$i')"))

// Verify inserts
spark.table("potato").count // 9 records

我们使用外部目录的listPartitionsdropPartitions 函数。

// Get External Catalog
val catalog = spark.sharedState.externalCatalog

// Get the spec from the list of all partitions 
val partitions = catalog.listPartitions("default", "potato").map(_.spec)

// We pass them to the Catalog's dropPartitions function.
// If you purge data, it gets deleted immediately and isn't moved to trash.
// This takes precedence over retainData, so even if you retainData but purge,
// your data is gone.
catalog.dropPartitions("default", "potato", partitions,
                   ignoreIfNotExists=true, purge=true, retainData=false)
spark.table("potato").count // 0 records
catalog.listPartitions("default", "potato").length // 0 partitions

这对MANAGED 表非常有效,但是EXTERNAL 表呢?

// We repeat the setup above but after creating an EXTERNAL table
// After dropping we see that the partitions appear to be gone (or are they?).
catalog.listPartitions("default", "potato").length // 0 partitions

// BUT repairing the table simply adds them again, the partitions/data 
// were NOT deleted from the underlying filesystem. This is not what we wanted!
spark.sql("MSCK REPAIR TABLE potato")
catalog.listPartitions("default", "potato").length // 9 partitions again!   

为此,我们在删除分区之前将表从EXTERNAL 更改为MANAGED

import org.apache.spark.sql.catalyst.TableIdentifier
import org.apache.spark.sql.catalyst.catalog.CatalogTable
import org.apache.spark.sql.catalyst.catalog.CatalogTableType

// Identify the table in question
val identifier = TableIdentifier("potato", Some("default"))

// Get its current metadata
val tableMetadata = catalog.getTableMetadata(identifier)

// Clone the metadata while changing the tableType to MANAGED
val alteredMetadata = tableMetadata.copy(tableType = CatalogTableType.MANAGED)

// Alter the table using the new metadata
catalog.alterTable(alteredMetadata)

// Now drop!
catalog.dropPartitions("default", "potato", partitions,
                   ignoreIfNotExists=true, purge=true, retainData=false)
spark.table("potato").count // 0 records
catalog.listPartitions("default", "potato").length // 0 partitions
spark.sql("MSCK REPAIR TABLE potato") // Won't add anything
catalog.listPartitions("default", "potato").length // Still 0 partitions!

别忘了使用CatalogTableType.EXTERNAL将表格改回EXTERNAL

【讨论】:

    【解决方案2】:

    Hive 有两种类型的表(托管表和外部表)。托管表是为 Hive 管理整个架构和数据的目的而创建的。因此,删除 Hive 托管表会删除架构、元数据和数据。但是,外部表的数据位于其他位置(假设是外部源,例如 S3)。因此,删除表只会删除元数据和表,但数据在源中保持不变。

    在您的情况下,当您截断表时,Hive 应该维护元存储,因为表仍然存在于 Hive 中,只有数据被删除。此外,Metastore 不保存数据,因为它仅包含有关架构和其他相关表详细信息的信息。

    我希望它能在某种程度上回答。

    编辑1:

    Similar Post

    【讨论】:

    • 感谢您的回答。是的,它解释了为什么 truncate 不删除元数据,我理解这一点,但不幸的是它并没有解决我的问题。
    • 我发现了一个类似的查询,因此将其添加到我的答案中。如果您还没有看到它,可能会有所帮助。
    猜你喜欢
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2017-03-09
    • 2022-07-29
    • 2018-05-18
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多