原文:
towardsdatascience.com/delta-lake-type-widening-82935384a0f5
图片由 Luca Florio 在 Unsplash 提供
Delta Lake 正在发布新的大版本,当然,社区中每个人都广泛期待的功能有很多。其中之一被称为类型扩展,本文将致力于解释它是什么以及为什么它是有用的。
生活中唯一不变的是变化 – 赫拉克利特
赫拉克利特的名言不仅适用于我们所生活的世界,而且也适用于谈论数据,描述它的信息。我们正处于一个快节奏的商业环境时代,适应是跟上我们不断变化的世界中涌现出的所有新要求的关键。这些变化往往会导致我们数据的基本结构发生变化,因此我们需要能够适应这些变化,以保持对所描述内容的真实性。
在 Delta Lake 中,我们使用 Delta 表来描述我们的数据,并且有几种方法可以使用当前的架构演变功能无缝地适应这些更改。我们可以:添加一个更好地描述我们实体的新列;需要重命名以更相关名称的列;如果列顺序未优化,则重新排序列;如果我们不再需要它,则删除列;或者由于例如缺少刻度(数字无法放入整数中,需要存储在 long 中)而更改列的类型。虽然上述所有示例在 Delta Lake 中都已可能,但更改列类型需要重写整个表****,这并不理想,尤其是对于规模达到千兆字节的表。这就是类型扩展发挥作用的地方。
*****使用列映射有解决方案,但它们并不非常用户友好。
类型扩展
类型扩展允许将给定列的类型更改为更宽的类型(可以存储相同或更多信息)。
有两种类型的类型扩展,自动的,正如其名所示,是自动应用的,以及显式类型扩展,它将需要使用 ALTER TABLE 命令。所有自动类型更改都由显式类型更改支持。
自动
-
Byte → Short → Int → Long
-
Float → Double
-
小数刻度和精度增加(6,2)→(10,4)
-
Date → TimestampNTZ (无时区的时间戳)
-
varchar(x) → varchar(y) – (x < y)
-
varchar(x) → string
仅显式
-
int → double
-
byte/short/int/long → decimal
-
char(x) → char(y)/varchar(y) – (x < y)
-
char(x) → string
这些更改也支持嵌套字段以及数组或映射内部。
如何使用它?
如前所述,我们可以进行自动或显式类型扩展。要使用此功能,我们需要启用它,如下所示:
ALTER TABLE t SET TBLPROPERTIES ('delta.enableTypeWidening' = true)
对于自动的,在为我们将要写入的表格启用功能后,我们需要确保会话已启用模式演变,以便在源包含比相应目标更宽的类型时自动扩展类型。
可以像这样启用模式演变:
write(Stream).option("mergeSchema", "true")
or
SET spark.databricks.delta.schema.autoMerge.enabled = true
对于显式的类型提升,我们明确运行带有请求(有效)变更的 ALTER TABLE 命令:
ALTER TABLE t CHANGE COLUMN col TYPE type
类型变更时会发生什么?
当类型被扩展时,表格的模式通过元数据操作进行更改。即使已经存在的文件是用不同的模式编写的,它们仍然保持不变,如果没有启用类型提升,我们本应需要重写所有这些文件以获得相同的结果。
表格类型从整数变为长整型 - 图片由作者提供
为了维护模式中所有变更的历史记录,将在相关字段的元数据下存储附加信息,这将成为作者协议的一部分。以下是在映射键中此类变更的示例:
{
"name" : "mapColumn",
"type" : {
"type": "map",
"keyType": "integer",
"valueType": "long",
"valueContainsNull": true
},
"nullable" : true,
"metadata" : {
"delta.typeChanges": [
{
"tableVersion": 2,
"fromType": "short",
"toType": "integer",
"fieldPath": "value"
},
{
"tableVersion": 5,
"fromType": "integer",
"toType": "long",
"fieldPath": "value"
}
]
}
}
四条信息将存储在 delta.typeChanges 中的元数据字段下:
-
tableVersion – 应用变更时的表格版本
-
fromType – 变更前的列类型
-
toType – 变更后的列类型
-
fieldPath(可选) – key、value 和 element 分别用于表示映射的键、值和数组类型。对于嵌套数组和映射,它使用从父级开始的完整路径作为前缀
此信息将由读者使用,以便他们在读取仍包含 fromType 类型的旧文件时提升类型。
随着时间的推移,UPDATE/MERGE 操作将运行并触发所有仍在使用旧模式的文件的天然重写。
自然重写 – 图片由作者
在此情况下,如果所有文件都具有与最新元数据操作类型变更相同的模式,作者将移除存在于 delta.typeChanges 中的元数据信息。这样,读者可以无需对包含先前类型的文件进行特殊处理即可读取表格。
如何禁用类型提升?
要完全禁用此功能,我们只需将其设置为 false:
ALTER TABLE t SET TBLPROPERTIES ('delta.enableTypeWidening' = false)
or
ALTER TABLE t DROP FEATURE typeWidening
禁用类型提升后,Delta 需要确保所有不兼容的读者都可以无问题地读取表格。
如果在可用的历史记录中没有对类型进行更改,则该特性将成功删除。然而,如果当前表版本包含类型更改,则将触发所选文件的重写(RowCommitVersion ≥ 包含类型更改的最新元数据操作)以及所有类型拓宽元数据将被移除。作业执行后,将抛出异常,提示用户在保留期过期后重新运行DROP FEATURE命令。对于仅包含历史版本中类型拓宽残留的表(仅通过时间旅行可用),将仅抛出异常,提示在保留期过期后重新运行命令,类似于前一种情况。
结论
在这篇帖子中,我们学习了类型拓宽(Type Widening)的概念及其重要性,它允许在不进行完整表重写的情况下进行类型更改。这个特性在撰写本文时仍在开发中(见:github.com/delta-io/delta/issues/2622),可能会发生变化,但总体思路是类型更改应该更加用户友好,并且不需要复杂的操作。在此期间,让我们等待 Delta 的新主要版本及其将包含的所有酷炫特性!
如果你希望阅读我关于高度请求的 Delta Lake 特性——液态聚类(Liquid Clustering)的最新帖子,请确保在以下链接阅读:
1794

被折叠的 条评论
为什么被折叠?



