变体与 JSON 字符串有何不同?

重要

此功能目前以公共预览版提供。

本文介绍使用变体数据类型时的行为变化以及语法和语义的差异。 本文假设你知道如何在 Azure Databricks 上处理 JSON 字符串数据。 对于 Azure Databricks 的新用户,在存储需要灵活更改或未知架构的半结构化数据时,应使用 JSON 字符串的变体。 请参阅对半结构化数据建模

在 Databricks Runtime 15.3 及更高版本中,可以使用变体数据类型来编码和查询半结构化数据。 Databricks 建议使用变体来替代使用 JSON 字符串存储半结构化数据的做法。 变体的读写性能提高使其能够在某些用例中取代原生的 Spark 复杂类型,例如结构和数组。

如何查询变体数据?

变体数据使用相同的运算符来查询字段、子字段和数组元素。

若要查询某个字段,请使用 :。 例如 column_name:field_name

若要查询某个子字段,请使用 .。 例如 column_name:field_name.subfield_name

若要查询数组元素,请使用 [n],其中 n 是元素的整数索引值。 例如,若要查询数组中的第一个值,请使用 column_name:array_name[0]

从 JSON 字符串升级到变体时,以下差异可能会破坏现有查询:

  • 所有变体路径元素均以区分大小写的方式进行匹配。 JSON 字符串不区分大小写。 这意味着,对于变体,column_name:FIELD_NAMEcolumn_name:field_name 在存储的数据中查找不同的字段。
  • [*] 语法不支持识别或解包数组中的所有元素。
  • 变体以不同于 JSON 字符串的方式对 NULL 值进行编码。 请参阅变量 null 规则

在 JSON 字符串与变体之间来回转换

在 Databricks Runtime 15.3 及更高版本中,to_json 函数具有将 VARIANT 类型强制转换为 JSON 字符串的附加功能。 将 VARIANT 转换为 JSON 字符串时,将忽略选项。 请参阅 to_json

parse_json 函数将 JSON 字符串转换为 VARIANT 类型。 虽然 parse_json(json_string_column)to_json(variant_column) 的逻辑反函数,但以下转换规则描述了为什么它不是确切的反函数:

  • 空白字符不会完美保留。
  • 键的排序是任意的。
  • 可能会截断数字中的尾随零。

如果 JSON 字符串格式不正确或超出变体大小限制,则 parse_json 函数将返回错误。 如果在分析过程中出现错误,则使用 try_parse_json 函数返回 NULL

用于处理变体的 SQL 函数有哪些?

Databricks Runtime 15.3 及更高版本中提供的 Apache Spark SQL 函数提供了与变体数据交互的方法。 下表包括新函数、对应的 JSON 字符串函数以及行为差异的说明。

注意

若要将这些函数与 PySpark 数据帧一起使用,请从 pyspark.sql.functions 导入它们。 PySpark 不支持 variant_explodevariant_explode_outer

变体函数 JSON 字符串函数 备注
variant_get castget_json_object 采用表达式、路径和类型。 遵循变体路径、强制转换和 null 值的所有规则。
try_variant_get try_castget_json_object 采用表达式、路径和类型。 遵循变体路径、强制转换和 null 值的所有规则。
is_variant_null is null 检查表达式是否存储了 VARIANT 编码的 NULL。 使用 is null 检查输入表达式是否为 NULL
schema_of_variant schema_of_json 确定 ARRAY<elementType> 的架构时,如果在数据中发现冲突的类型,则 elementType 可能被推理为 VARIANT
schema_of_variant_agg schema_of_json_agg 未识别到最不常用的类型时,类型将派生为 VARIANT
variant_explode explode 输出 poskeyvalue 列。 当分解数组时,输出键始终为 null。
variant_explode_outer explode_outer 输出 poskeyvalue 列。 当分解数组时,输出键始终为 null。

变体以不同于 JSON 字符串的方式处理强制转换和 NULL。 请参阅变体类型强制转换规则变体 null 规则