Paimon Variant是一种面向半结构化数据的高性能列式存储类型,基于元数据索引与Shredding技术实现高效随机访问与查询下推。本文为您介绍如何在EMR Serverless Spark中通过parse_json写入Variant数据,并使用variant_get进行类型安全、可下推的路径查询。
Variant说明
Variant是一种新型数据类型,用于高效存储和查询半结构化数据(如JSON)。它通过以下特性优化性能:
基于元数据高效随机访问:写入时抽取元数据编码写入,支持高效随机访问。
Shredding技术:通过列化技术,减少IO开销,提升查询效率。
标准支持:基于Parquet,兼容主流存储格式。
支持版本
仅esr-5.1.0 及之后引擎版本支持本文操作。
使用示例
本示例演示如何将JSON String转换为Variant数据类型,并高效查询数据。
写入数据
进入数据开发页面。
在左侧导航栏,选择。
在Spark页面,单击目标工作空间名称。
在EMR Serverless Spark页面,单击左侧导航栏中的数据开发。
新建任务。
在开发目录页签下,单击
图标。在新建对话框中,输入名称(例如variant_test_task),类型使用默认的SparkSQL,然后单击确定。
在数据库下拉列表中选择一个数据库,在会话下拉列表中选择一个已启动的会话实例。
您也可以在下拉列表中选择创建SQL会话,直接创建一个新的会话实例。会话管理更多介绍,请参见管理SQL会话。
说明SQL会话建议添加以下Spark配置
# 读时自动剪裁 spark.sql.variant.pushVariantIntoScan true # 写入时自动shredding spark.paimon.variant.inferShreddingSchema true拷贝如下代码到新增的Spark SQL页签(variant_test_task)中。单击运行,执行创建的任务。
--创建表 CREATE TABLE variant_tbl (id INT, v VARIANT) USING paimon; --通过parse_json将JSON String转换为Variant,再写入目标表(否则写入的只是String类型的Variant) INSERT INTO variant_tbl SELECT id, CASE WHEN id = 0 THEN parse_json('{"age":21,"city":"Beijing"}') WHEN id = 1 THEN parse_json('{"age":27}') WHEN id = 2 THEN parse_json('{"city":"Beijing", "other":"xxx"}') WHEN id = 3 THEN parse_json('{"other":"yyy"}') WHEN id = 4 THEN parse_json('{"age":28}') WHEN id = 5 THEN parse_json('{"age":27,"city":"Hangzhou"}') WHEN id = 6 THEN parse_json('{"age":29,"city":"Beijing"}') END AS v FROM range(7);说明除了通过在SQL会话中配置
spark.paimon.variant.inferShreddingSchema =true实现写入时自动推断shreddingSchema外,还支持在建表时指定shreddingSchema。CREATE TABLE variant_tbl (id INT, v VARIANT) TBLPROPERTIES ('parquet.variant.shreddingSchema' = '{"type":"ROW","fields": [{"name":"v", "type":{"type":"ROW", "fields":[{"name":"age","type":"INT"},{"name":"city","type":"STRING"}]}}]}' )
查询数据
使用 variant_get 函数从 VARIANT 列中按路径提取强类型字段,语义等价于 get_json_object,但具备类型安全与下推能力。
函数语法
variant_get(c, path, type)参数说明
参数
说明
cVARIANT类型列名path路径
根路径:
$嵌套字段:
$.user.name数组索引:
$.items[0].id
type目标数据类型(例如:
int,string,boolean)。查询示例
SELECT variant_get(v, '$.age', 'int') AS age, variant_get(v, '$.city', 'string') AS city, variant_get(v, '$.other', 'string') AS other FROM variant_tbl;
使用建议
当需要对查询结果进行进一步处理时,建议通过子查询提前提取字段,以触发列裁剪优化,从而显著减少数据扫描量。
SELECT
max(age),
city
FROM (
SELECT
variant_get(v, '$.age', 'int') AS age,
variant_get(v, '$.city', 'string') AS city
FROM variant_tbl
)
GROUP BY city;