跳到主要内容
版本:Latest-4.1

VARIANT

important

VARIANT 类型仅支持 Iceberg Catalog 中的表,不支持 StarRocks 原生表。

从 v4.1 版本起,StarRocks 支持 VARIANT 数据类型,用于查询 Parquet 格式的 Iceberg 表中的半结构化数据。本文介绍 VARIANT 的基本概念,以及 StarRocks 如何查询 VARIANT 类型数据并通过 VARIANT 函数对其进行处理。

什么是 VARIANT

VARIANT 是一种半结构化数据类型,可以存储不同数据类型的值,包括基本类型(整数、浮点数、字符串、布尔值、日期、时间戳)和复杂类型(结构体、映射、数组)。VARIANT 数据以二进制格式编码,以实现高效的存储和查询。

VARIANT 类型在处理使用 Parquet 格式并采用 variant 编码的 Apache Iceberg 表数据时尤为有用,它支持灵活的 Schema 演进以及异构数据的高效存储。

有关 Parquet variant 编码格式的更多信息,请参阅Parquet Variant 编码规范

使用 VARIANT 数据

从 Iceberg 表查询 VARIANT 类型数据

StarRocks 支持从以 Parquet 格式存储的 Iceberg 表中查询 VARIANT 类型数据。在查询使用 Parquet variant 编码的 Iceberg 表时,VARIANT 列会被自动识别。

查询包含 VARIANT 列的 Iceberg 表示例:

-- 查询包含 VARIANT 列的表
SELECT
id,
variant_col
FROM iceberg_catalog.db.table_with_variants;

从 VARIANT 数据中提取值

StarRocks 提供了多个函数,用于从 VARIANT 数据中提取带类型的值。

示例 1:使用带类型的 getter 函数提取基本类型值。

SELECT
get_variant_int(variant_col, '$') AS int_value,
get_variant_string(variant_col, '$') AS string_value,
get_variant_bool(variant_col, '$') AS bool_value,
get_variant_double(variant_col, '$') AS double_value
FROM iceberg_catalog.db.table_with_variants;

示例 2:使用 JSON 路径表达式导航嵌套结构。

SELECT
get_variant_string(variant_col, '$.user.name') AS user_name,
get_variant_int(variant_col, '$.user.age') AS user_age,
get_variant_string(variant_col, '$.address.city') AS city
FROM iceberg_catalog.db.table_with_variants;

示例 3:访问数组元素。

SELECT
get_variant_int(variant_col, '$.scores[0]') AS first_score,
get_variant_int(variant_col, '$.scores[1]') AS second_score
FROM iceberg_catalog.db.table_with_variants;

示例 4:查询嵌套 variant 数据并返回 VARIANT 类型。

SELECT
variant_query(variant_col, '$.metadata') AS metadata,
variant_query(variant_col, '$.items[0]') AS first_item
FROM iceberg_catalog.db.table_with_variants;

示例 5:检查 VARIANT 值的类型。

SELECT
variant_typeof(variant_col) AS root_type,
variant_typeof(variant_query(variant_col, '$.data')) AS data_type
FROM iceberg_catalog.db.table_with_variants;

将 JSON 转换为 VARIANT

StarRocks 支持将 JSON 值转换为 VARIANT。如果输入为 STRING,请先将其转换为 JSON。

SELECT
CAST(parse_json('{"id": 1, "flags": {"active": true}, "scores": [1.5, null]}') AS VARIANT) AS variant_value;
SELECT
CAST(json_col AS VARIANT) AS variant_value
FROM db.table_with_json;

将 VARIANT 数据转换为 SQL 类型

您可以使用 CAST 函数将 VARIANT 数据转换为标准 SQL 类型:

SELECT
CAST(variant_query(variant_col, '$.count') AS INT) AS count,
CAST(variant_query(variant_col, '$.price') AS DECIMAL(10, 2)) AS price,
CAST(variant_query(variant_col, '$.active') AS BOOLEAN) AS is_active,
CAST(variant_query(variant_col, '$.name') AS STRING) AS name
FROM iceberg_catalog.db.table_with_variants;

复杂类型也可以从 VARIANT 进行转换:

SELECT
CAST(variant_col AS STRUCT<id INT, name STRING>) AS user_struct,
CAST(variant_col AS MAP<STRING, INT>) AS config_map,
CAST(variant_col AS ARRAY<DOUBLE>) AS values_array
FROM iceberg_catalog.db.table_with_variants;

将 SQL 类型转换为 VARIANT

您可以将 SQL 值转换为 VARIANT。支持的输入类型包括 BOOLEAN、整数类型、FLOAT/DOUBLE、DECIMAL、STRING/CHAR/VARCHAR、JSON、DATE/DATETIME/TIME 以及复杂类型(ARRAY、MAP、STRUCT)。对于 MAP,键在编码时会被转换为字符串。不支持 HLL、BITMAP、PERCENTILE 和 VARBINARY 等类型。

SELECT
CAST(123 AS VARIANT) AS v_int,
CAST(3.14 AS VARIANT) AS v_double,
CAST(CAST('12.34' AS DECIMAL(10, 2)) AS VARIANT) AS v_decimal,
CAST('hello' AS VARIANT) AS v_string,
CAST(PARSE_JSON('{"k":1}') AS VARIANT) AS v_json;

VARIANT 函数

VARIANT 函数可用于查询和提取 VARIANT 列中的数据。有关详细信息,请参阅各函数文档:

  • variant_query:查询 VARIANT 值中的路径并返回 VARIANT
  • get_variant:从 VARIANT 中提取带类型的值(int、bool、double、string)
  • variant_typeof:返回 VARIANT 值的类型名称

VARIANT 路径表达式

VARIANT 函数使用 JSON 路径表达式来导航数据结构。路径语法与 JSON 路径类似:

  • $ 表示 VARIANT 值的根
  • . 用于访问对象字段
  • [index] 用于访问数组元素(从 0 开始索引)
  • 包含特殊字符(如点号)的字段名可以加引号:$."field.name"

路径表达式示例:

$                      -- Root element
$.field -- Object field access
$.nested.field -- Nested field access
$."field.with.dots" -- Quoted field name
$[0] -- First array element
$.array[1] -- Second element of array field
$.users[0].name -- Nested array access
$.config["key"] -- Map-style access

数据类型转换

从具有 variant 编码的 Parquet 文件读取数据时,支持以下类型转换:

Parquet Variant 类型StarRocks VARIANT 类型
INT8, INT16, INT32, INT64int8, int16, int32, int64
FLOAT, DOUBLEfloat, double
BOOLEANboolean
STRINGstring
DATEDate
TIMESTAMP, TIMESTAMP_NTZTimestamp
DECIMALDecimal, float, double
STRUCTObject
MAPObject
ARRAYArray

限制与注意事项

  • VARIANT 支持从 Parquet 格式的 Iceberg 表中读取具有 variant 编码的数据,以及使用 StarRocks 文件写入器写入 Parquet 文件(非分片 variant 编码)。
  • VARIANT 值的大小限制为 16 MB。
  • 目前读写均仅支持非分片 variant 值。
  • VARIANT 可通过从 JSON 值或支持的 SQL 类型(包括 ARRAY、MAP 和 STRUCT)进行类型转换来创建。
  • 嵌套结构的最大深度取决于底层 Parquet 文件结构。
Rocky the happy otterStarRocks Assistant

AI generated answers are based on docs and other sources. Please test answers in non-production environments.