半结构化数据建模

本文建议存储半结构化数据的模式,具体取决于组织使用数据的方式。 Azure Databricks 提供函数、本机数据类型和查询语法,用于处理半结构化、嵌套和复杂数据。

以下注意事项会影响对应使用的模式的选择:

  • 数据源中的字段或类型是否经常更改?
  • 数据源中包含多少个唯一字段?
  • 是否需要针对写入或读取优化工作负荷?

Databricks 建议将数据存储为用于下游查询的 Delta 表。

使用变体

在 Databricks Runtime 15.3 及更高版本中,可以使用 VARIANT 类型来存储半结构化 JSON 数据,该数据采用优化的编码,其在读取和写入性能方面优于 JSON 字符串。

VARIANT 类型具有与 JSON 字符串类似的应用程序。 某些工作负荷仍受益于使用结构、映射和数组,尤其是对于具有已知架构的数据,这些架构将受益于优化的数据布局和统计信息收集。

有关更多详细信息,请参阅以下文章:

使用 JSON 字符串

可以使用标准 JSON 格式将数据存储在单个字符串列中,然后使用 : 表示法查询 JSON 中的字段。

许多系统将记录输出为字符串或字节编码的 JSON 记录。 引入和存储这些记录作为字符串的处理开销非常低。 还可以使用 to_json 函数将任何数据结构转换为 JSON 字符串。

选择将数据存储为 JSON 字符串时,请考虑以下优缺点:

  • 所有值都存储为字符串,没有类型信息。
  • JSON 支持可以使用文本表示的所有数据类型。
  • JSON 支持任意长度的字符串。
  • 单个 JSON 数据列中可以表示的字段数没有限制。
  • 在写入表之前,无需对数据进行预处理。
  • 可以解决下游工作负荷中的数据中存在的类型问题。
  • JSON 在读取时提供最差的性能,因为必须分析每个查询的整个字符串。

JSON 字符串提供了极大的灵活性和易于实现的解决方案,用于将原始数据引入 Lakehouse 表。 可以选择对许多应用程序使用 JSON 字符串,但在工作负荷最重要的结果存储数据源的完整准确表示形式以供下游处理时,它们特别有用。 某些用例可能包括:

  • 从队列服务(如 Kafka)引入流数据。
  • 记录响应 REST API 查询。
  • 从不由团队控制的上游数据源存储原始记录。

假设引入逻辑很灵活,即使遇到新字段、数据结构更改或数据源中的类型更改,存储数据作为 JSON 字符串也应具有复原能力。 虽然下游工作负荷可能会由于这些更改而失败,但表包含源数据的完整历史记录,这意味着无需返回到数据源即可修正问题。

使用结构

可以使用结构存储半结构化数据,并在维护数据源的嵌套结构的同时启用列的所有本机功能。

Delta Lake 将存储的数据视为与其他任何列相同的结构,这意味着它与结构和列没有功能差异。 Delta Lake 使用的 Parquet 数据文件为结构中的每个字段创建一列。 可以使用结构字段作为聚集列或分区列,并且可以收集有关跳过数据的结构的统计信息。

结构通常提供读取时的最佳性能,因为它们支持跳过优化的所有数据,并将单个字段存储为列。 当存在的列数达到数百个时,性能可能会开始受到影响。

结构中的每个字段都有一个数据类型,该数据类型在写入时强制与列相同。 因此,结构需要对数据进行完全预处理。 如果只想将已验证的数据提交到表,但在处理上游系统中格式不正确的记录时,可能会导致数据被删除或作业失败。

结构比用于架构演变的 JSON 流更灵活,无论是用于演变数据类型还是添加新字段。

使用地图和数组

可以使用地图和数组的组合在 Delta Lake 中本机复制半结构化数据格式。 不能对这些类型定义的字段收集统计信息,但它们为具有大约 500 个字段的半结构化数据集的读取和写入提供均衡的性能。

映射的键和值都是键入的,因此数据是预处理的,架构是在写入时强制执行的。

为了加速查询,Databricks 建议存储通常用于将数据筛选为单独的列的字段。

我是否需要平展数据?

如果要使用 JSON 或映射存储数据,请考虑存储经常用于将查询筛选为列的字段。 统计信息集合、分区和聚类分析不适用于 JSON 字符串或映射中的字段。 对于作为结构存储的数据,无需执行此操作。

用于处理嵌套数据的语法

查看以下资源,了解有关使用嵌套数据的信息: