了解开放表格式
作者:Avril Aysha
本文解释了什么是开放表格式,以及为什么它们是存储表格数据的绝佳选择。
您将了解使用开放表格式与传统数据存储技术的优势。您还将了解不同类型的开放表格式,以及 Delta Lake UniForm、XTable 和 Unity Catalog 等项目如何让您与任何表格式互操作。
开放表格式比将数据存储为 CSV 和 Parquet 等文件格式更高效、更可靠。开放表格式支持 ACID 事务、更高级的数据跳过、时间旅行功能以及其他出色的功能,这些功能将使您的数据工作更快、更安全。
Delta Lake 是一种流行的开放表格式。还有其他开放表格式,如 Apache Iceberg 和 Apache Hudi。
尽管不同的开放表格式之间存在差异,但随着支持互操作性的技术出现,这些差异正变得越来越不重要。Delta Lake UniForm 和 Unity Catalog 等项目正在弥合开放表格式之间的差距。我们将在文章末尾介绍这些项目。
首先,让我们深入了解什么是开放表格式以及它们为何如此出色 😀
什么是开放表格式?
开放表格式是一种用于存储表格数据的开源技术,它构建在现有的文件格式(如 Parquet 和 ORC)之上。开放表格式将您的表格数据存储在文件中,并将元数据(关于您的数据和操作)存储在单独的文件或目录中。此元数据用于启用开放表格式的许多强大功能:更快的查询速度、更可靠的事务和更低的数据损坏风险。
三种主要的开放表格式是 Delta Lake、Apache Hudi 和 Apache Iceberg。
为什么要使用开放表格式?
开放表格式解决了传统数据湖的性能和可靠性问题。通过将元数据与表格数据一起存储,开放表格式为您提供了强大的功能,例如:
- 可靠的 ACID 事务
- 高级数据跳过
- 时间旅行
- 模式强制和演进
- 完整的 CRUD 操作
让我们在下面的部分中探讨每个功能。
开放表格式:可靠的 ACID 事务
开放表格式旨在为数据湖生态系统带来 ACID 保证。ACID 事务使您的数据写入更可靠,因此操作不会损坏您的表。“事务”是指任何更改表状态的写入操作。
通过 ACID 事务,您可以确保避免:
- 中断下游查询的失败部分写入
- 意外数据损坏
- 冲突的并发进程或数据版本
- 意外数据丢失
在Delta Lake 与数据湖一文中阅读更多内容。
开放表格式:高级数据跳过
开放表格式比 Parquet 和 CSV 等文件格式提供更高级的数据跳过。由于它们将元数据存储在集中式元数据目录中,查询引擎可以轻松找到选择性查询的相关数据。
Delta Lake 通过 (1) 集中式事务日志中高效的元数据存储和 (2) 通过 Z-ordering 或 Liquid Clustering 优化的数据布局来支持高级数据跳过。这些策略将使您的查询运行得更快。
在 [数据跳过指南] (#add-when-live) 中阅读更多内容。
开放表格式:时间旅行
开放表格式支持时间旅行。这意味着您可以轻松检查数据集的早期版本,并在需要时恢复到这些版本。
Delta Lake 通过其事务日志支持数据版本控制。您对数据所做的所有更改都记录在此日志中。这意味着您可以轻松查看以前的版本,并在需要时纠正意外错误。
您可以像这样加载 Delta 表的特定版本:
spark.read.format("delta").option("versionAsOf", version).load("path/to/delta")
在Delta Lake 时间旅行文章中阅读更多内容。
开放表格式:模式强制和演进
为了确保数据一致性并避免损坏,您通常希望确保新数据与现有模式匹配。这称为模式强制。
许多标准文件格式(如 Parquet 和 CSV)默认不支持模式强制。这意味着您可以轻松地将具有不同模式的数据写入现有的 Parquet 数据湖,例如。这将在尝试读取数据时导致下游问题。
开放表格式默认内置模式强制。这可以防止您意外损坏数据。
让我们看看 Delta Lake 中的实际操作。
创建一个包含两列的 Delta 表:first_name
和 age
df = spark.createDataFrame([("bob", 47), ("li", 23), ("leonard", 51)]).toDF(
"first_name", "age"
)
df.write.format("delta").save("tmp/fun_people")
现在,尝试将具有不同模式的数据写入此表
df = spark.createDataFrame([("frank", 68, "usa"), ("jordana", 26, "brasil")]).toDF(
"first_name", "age", "country"
)
df.write.format("delta").mode("append").save("tmp/fun_people")
此操作将因 AnalysisException 而报错。
Delta Lake 默认不允许您追加具有不匹配模式的数据。在您有意更新模式的情况下,您可以使用 mergeSchema
选项。
df.write.option("mergeSchema", "true").mode("append").format("delta").save(
"tmp/fun_people"
)
阅读Delta Lake 模式强制和Delta Lake 模式演进文章以了解更多信息。
开放表格式:完整的 CRUD 操作
常规的 Parquet 文件是不可变的。更改 Parquet 文件的唯一方法是完全覆盖它。这是一个特性:它可以防止您意外损坏数据。
像 Delta Lake 这样的开放表格式比常规的 Parquet 文件为您提供更高的可靠性和更大的灵活性。您可以使用开放表格式对数据子集执行 CRUD(创建、读取、更新、删除)操作。
例如,您可以使用 Delta Lake replaceWhere 操作选择性地覆盖表中的特定行:
(
df.write.format("delta")
.option("replaceWhere", "number > 2")
.mode("overwrite")
.save("tmp/my_data")
)
开放表格式将这类部分数据更新视为“逻辑操作”。删除或覆盖操作只是更改事务日志中的标记,以指向新行或新列。实际数据不受影响。这样,您就可以安全地对数据进行部分更改,而无需执行昂贵的重写。
我可以一起使用不同的开放表格式吗?
是的,您可以一起使用不同的开放表格式,但这需要仔细规划。Delta Lake、Apache Iceberg 和 Apache Hudi 等开放表格式最初旨在独立管理数据集。每种格式都有自己的元数据结构、事务管理和 API。这可能会使互操作性变得棘手。
Delta Lake UniForm 和 Apache XTable 等项目正在努力统一开放表格式的工作流程。例如,您可以使用 Delta Lake 进行 您的 ETL 工作负载,然后使用 UniForm 将您的数据作为 Iceberg 表读取到下游 BI 和分析系统中。
Unity Catalog 是另一个致力于改进开放表格式互操作性的项目。通过 Unity Catalog,您可以存储、管理和访问 Delta Lake 和 Iceberg 格式的表格数据。
阅读统一开放表格式文章以了解更多信息。
我可以将开放表格式转换为 Parquet 等文件格式吗?
是的,在大多数情况下,您可以将以开放表格式(例如 Delta Lake)存储的表转换为其底层文件格式(例如 Parquet)。
例如,要将 Delta 表转换为具有 Hive 样式分区的 Parquet 数据湖,您只需:
- 清理任何陈旧文件
- 删除事务日志目录
从纯性能角度来看,如果可以避免,通常不应从 Delta Lake 转换为 Parquet。Delta Lake 几乎总是更快、更可靠。仅在您确定不再需要版本控制或事务管理等功能时才这样做。
我应该何时使用开放表格式?
开放表格式几乎总是比使用 Parquet、CSV 或 JSON 等文件格式的数据湖更快、更安全、更对开发人员友好。像 Delta Lake 这样的开放表格式可能是您的绝佳选择,因为它们:
- 支持事务和模式强制,因此损坏表的可能性大大降低。
- 将文件元数据抽象到事务日志中,并支持高级集群和数据跳过,因此您可以更快地运行查询。
- 使执行常见数据操作(如删除列、重命名列、删除行和 DML 操作)变得容易。
如果您正在生产中运行重要的表格数据工作流,开放表格式可能是您的最佳选择。