Delta Lake當(dāng)前版本(0.5)只支持API操作的,但是實(shí)現(xiàn) Insert SQL 語法也不難,可以參考 Delta Lake 平臺(tái)化實(shí)踐(離線篇),需要注意的是 Delta Lake 中的分區(qū)表覆蓋寫入操作。
INSERT OVERWRITE
INSERT OVERWRITE TABLE
分區(qū)表時(shí)分三種場(chǎng)景:
- 動(dòng)態(tài)分區(qū) - 寫入前會(huì)刪除所有分區(qū),并根據(jù)數(shù)據(jù)中的分區(qū)字段寫入相應(yīng)新分區(qū)
- 靜態(tài)分區(qū) - 只會(huì)對(duì)指定的分區(qū)進(jìn)行覆蓋寫操作
- 混合分區(qū)(動(dòng)態(tài)+靜態(tài)分區(qū)) - 上述兩種情況的結(jié)合
如果想通過 SQL 轉(zhuǎn)化為上述 API ,首先需要在 sql parser 的時(shí)候獲取到 insertMode 和 partitions 信息,并將 partitions 信息存在一個(gè)有序的結(jié)構(gòu)中,例如 LinkedHashMap。然后利用這些信息,就可以拼裝進(jìn)行拼裝實(shí)現(xiàn)上述三種場(chǎng)景。
動(dòng)態(tài)分區(qū)
對(duì)所有 ds 分區(qū)進(jìn)行覆蓋寫操作,將會(huì)清空所有 ds 分區(qū)
sql
INSERT OVERWRITE TABLE db.tableA partition(ds) select name,ds from db.tableB
Delta Lake API
df.write.format("delta").mode("overwrite").partitionBy(ds)
靜態(tài)分區(qū)
對(duì) ds=20200101 的分區(qū)進(jìn)行覆蓋寫操作,如果數(shù)據(jù)中沒有分區(qū)字段,需要使用 withColumn 增加相應(yīng)數(shù)據(jù)。
sql
INSERT OVERWRITE TABLE db.tableA partition(ds=20200101) select name from db.tableB
Delta Lake API
df.write.format("delta").mode("overwrite").option("replaceWhere", "ds = 20200101").partitionBy(ds)
tips: Delta 不能直接將數(shù)據(jù)寫入分區(qū)目錄,因?yàn)樗械?_Delta_Log 都存在表的根目錄下。
混合分區(qū)
對(duì) ds=20200101 中的所有 event 的分區(qū)進(jìn)行覆蓋寫操作,將會(huì)清空所有 event 分區(qū)
sql
INSERT OVERWRITE TABLE db.tableA partition(ds=20200101,event) select name,event from db.tableB
Delta Lake API
df.write.format("delta").mode("overwrite").option("replaceWhere", "ds = 20200101").partitionBy(ds,event)
后記
分區(qū)操作,一定要保證 partition 信息的有序
-
新表需要從 hive metastore 中獲取 partition 信息,Delta Table 在第一次寫入數(shù)據(jù)前,是不會(huì)生成
_DELTA_LOG
目錄的,此時(shí)可以從 hive metastore 中獲取建表時(shí)的分區(qū)名和其對(duì)應(yīng)的類型,例如://ddl: `ds` INT COMMENT 'ds' val ddl = spark.sharedState.externalCatalog.getTable(dbName, tableName).partitionSchema.toDDL val partitionNameAndType = new mutable.HashMap[String, String]() ddl.split(",").foreach { r => val x = r.split(" ") partitionNameAndType.put(x(0).replace("`", ""), x(1)) }
-
語義不同
Hive Table 直接使用 insert overwrite 動(dòng)態(tài)分區(qū)只會(huì)覆蓋數(shù)據(jù)涉及到的分區(qū),而 Spark 和 Delta Lake 的 API 則會(huì)將所有所有分區(qū)進(jìn)行覆蓋。Spark 2.3 以后也可以通過下述API實(shí)現(xiàn) Hive insert overwrite 語義
spark.conf.set("spark.sql.sources.partitionOverwriteMode","dynamic") data.write.mode("overwrite").insertInto("partitioned_table")
-
動(dòng)態(tài)分區(qū)覆蓋寫是高危操作
該操作很有可能會(huì)刪除一些你不期望的數(shù)據(jù),所以 Delta Lake 目前的 API 提供了 replaceWhere option 進(jìn)行約束