datainfra前沿动态 · Vol.21

AWS Spark 4.0 GA让emr-spark-8.0重塑大数据运行时;Iceberg V3 VARIANT在EMR上从规范走向生产二进制编码;Medium特征存储重设计揭示数据模型即瓶颈

第二十一期聚焦DataInfra三条动态:6月9日AWS宣布Apache Spark 4.0在Amazon EMR上全面可用——emr-spark-8.0运行时捆绑Iceberg 1.10/Delta 4.0/Hudi 1.0.2,Spark Connect首次登陆EMR Serverless实现本地IDE远程执行,VARIANT数据类型原生存储在Iceberg V3表中,SQL Scripting/Python Data Source API/transformWithState流式状态管理三大范式革新,EMR优化运行时较开源Spark 4.5倍性能提升,Serverless Storage降低Shuffle密集型工作负载20%成本——Spark 4.0从Databricks Runtime 18的'平台内体验'走向'全球最大Spark部署平台的生产就绪';同期AWS发布Iceberg V3 VARIANT在EMR上的首个生产实现详解——VARIANT在Parquet中以binary metadata+binary value+typed_value group三部分存储实现列式裁剪,parse_json()将JSON字符串转换为二进制格式写入,variant_get()按路径提取特定字段仅读取对应子列,Glue Data Catalog作为元数据管理端到端集成,AWS Lake Formation细粒度访问控制(VARIANT列暂不支持FGAC)——从Vol.7报道Iceberg 1.11.0 VARIANT规范到Vol.12报道Databricks平台VARIANT GA再到本期EMR生产实现,VARIANT完成'规范→平台支持→云端生产'三步走;The New Stack 6月9日报道Medium特征存储从关系型模型到列表型模型的重设计——原关系型特征90.2%读取行被直接丢弃/获取1000个实体需要1000次查询/过度依赖ALLOW FILTERING,重设计为列表特征单分区查询/ScyllaDB P99延迟从DynamoDB的40-120ms降至个位数毫秒/TTL自动过期无需清理逻辑——三条动态共同指向数据基础设施的'编码效率'主线:Spark 4.0 VARIANT将半结构化数据从文本编码推进到二进制列式编码(减少解析开销和存储空间),Iceberg V3 VARIANT在Parquet中实现typed_value组裁剪(查询仅访问所需子列),Medium特征存储将数据模型从关系型'二次查询'推进到列表型'单分区直达'(减少无效读取和查询次数)——三者都在消除数据路径上的'多余解码和多余读取'。

DataInfra AWS Amazon EMR Spark 4.0 emr-spark-8.0 Spark Connect EMR Serverless VARIANT Iceberg V3 Delta Lake 4.0 Apache Hudi 1.0.2 SQL Scripting Python Data Source API transformWithState Iceberg 1.10 Parquet typed_value variant_get parse_json Glue Data Catalog Lake Formation Medium Feature Store ScyllaDB DynamoDB 数据模型 特征存储 列表特征 关系型特征 列式裁剪 二进制编码 半结构化数据

第二十一期追踪到DataInfra领域三条重要动态:6月9日AWS宣布Apache Spark 4.0在Amazon EMR上全面可用——emr-spark-8.0运行时捆绑Iceberg 1.10/Delta 4.0/Hudi 1.0.2三大开放湖格式最新版本,Spark Connect首次登陆EMR Serverless让开发者从本地IDE直接连接远程Spark集群执行交互式PySpark,VARIANT数据类型原生存储在Iceberg V3表中结合列式裁剪和模式演变,SQL Scripting让ETL工作流完全留在SQL中无需切换Python/JVM,Python Data Source API让纯Python构建自定义数据连接器成为可能,transformWithState API实现可查询的结构化流式状态——EMR优化运行时较开源Spark 4.5倍性能提升,Serverless Storage降低Shuffle密集型工作负载20%成本——此前Vol.7报道Databricks Runtime 18 Beta搭载Spark 4.1从平台内体验新特性,本期EMR GA标志着Spark 4.0从’平台内创新’走向’全球最大Spark部署平台的生产就绪’;同期AWS发布Iceberg V3 VARIANT在EMR上的首个生产实现详解——VARIANT在Parquet中以binary metadata(类型和字典信息)+binary value(完整variant回退)+typed_value group(单个JSON字段被分解为独立Parquet子列)三部分存储,查询特定字段时Spark仅修剪typed_value group中包含该字段的子列而无需加载整个文档——从Vol.7报道Iceberg 1.11.0 VARIANT规范定义,到Vol.12报道Databricks平台Iceberg v3 GA宣布VARIANT全面支持,到本期EMR生产实现详解二进制编码和列式裁剪的具体工程,VARIANT完成’规范→平台支持→云端生产’三步走;The New Stack 6月9日报道Medium特征存储从关系型模型到列表型模型的重设计——原关系型特征将数据分割到两个表中(一个存实体ID一个存值)导致90.2%读取行被直接丢弃/获取1000个实体需要先查ID再逐个查值共1000次查询/过度依赖ALLOW FILTERING,重设计为列表特征将所有数据整合到单分区(feature_key+entity_id为分区键/timestamp DESC+MD5(value)为聚类键)实现一次查询获取完整数据,迁移到ScyllaDB后P99延迟从DynamoDB的40-120ms降至个位数毫秒/TTL自动过期无需清理逻辑——三条动态共同指向数据基础设施的’编码效率’主线:Spark 4.0 VARIANT将半结构化数据从文本编码推进到二进制列式编码,Iceberg V3 VARIANT在Parquet中实现typed_value组裁剪消除全文档解析,Medium特征存储将数据模型从关系型’二次查询’推进到列表型’单分区直达’——三者都在消除数据路径上的’多余解码和多余读取’。

AWS Spark 4.0 GA:emr-spark-8.0重塑大数据运行时三大范式

事件概述

6月9日,AWS宣布Apache Spark 4.0在Amazon EMR上全面可用,覆盖EMR on EC2、EMR on EKS和EMR Serverless三种部署模式。此次GA以emr-spark-8.0运行时为核心,捆绑Apache Iceberg 1.10、Apache Hudi 1.0.2和Delta Lake 4.0三大开放湖格式的最新版本,一次性将Spark生态的开放表格式栈推至当前最新状态。同日AWS发布5篇博客,分别覆盖GA总览、Spark Connect on EMR Serverless、VARIANT在Iceberg V3中的实现、Spark 4.0有状态流式应用和PySpark升级工具。

EMR优化运行时使Spark工作负载较开源Apache Spark快4.5倍——这不是Spark 4.0本身的功能,而是AWS长期以来对Spark运行时的持续优化(包括自适应查询执行增强、Shuffle优化和内存管理改进)。Serverless Storage可将Shuffle密集型工作负载成本降低20%。基础设施现代化方面:Python 3.11默认(支持3.12和3.13),Java 17默认(支持21),Scala 2.13,AWS SDK for Java v2替代v1,EMR S3A连接器替代EMRFS。

技术解析

  • Spark Connect on EMR Serverless——交互式PySpark从’部署-检查’到’本地-远程’:Spark Connect是Spark 4.0最显著的架构变革——应用代码和Spark驱动程序不再运行在同一JVM进程中,应用作为轻量级客户端通过gRPC向Spark服务器提交逻辑计划。EMR Serverless上的Spark Connect让开发者无需本地安装Spark、无需预配置集群,在VS Code/PyCharm/Jupyter/SageMaker/Kiro中直接编写PySpark代码并远程执行。每个Spark Connect会话拥有唯一的AWS资源ARN,支持会话级IAM权限和CloudTrail审计。连接断开后会话继续运行(默认空闲超时1小时),可重新连接不丢失工作。这消除了长期困扰Spark开发者的”部署-检查”循环——此前开发者需要在本地用样本数据开发,打包部署到集群后才发现问题。

  • VARIANT数据类型+Iceberg V3——半结构化数据从字符串到二进制列式:Spark 4.0引入VARIANT数据类型原生支持半结构化JSON数据——此前JSON数据要么预先定义模式(数据演变时破裂),要么存储为字符串(每次读取都需重型解析),要么宽表设计(浪费存储)。VARIANT使用parse_json()将JSON字符串转换为二进制格式,通过variant_get()按路径提取特定字段。在Iceberg V3表中VARIANT列可原生存储,结合Iceberg的模式演变和时间旅行功能。同时Iceberg V3还支持多参数分区转换(如range(order_date, product_category)产生单个复合键而非笛卡尔积)和未知类型处理(旧版读取器在新版写入器引入新列类型时不中断)。AWS Lake Formation通过细粒度访问控制(FGAC)提供列级和行级权限(VARIANT列暂不支持FGAC)。

  • SQL Scripting——ETL工作流留在SQL中:Spark 4.0引入SQL脚本编写能力,支持变量、IF/ELSE条件、循环和多语句块,无需切换到Python或JVM语言。此前复杂的ETL逻辑需要用Python/Scala包装SQL语句,SQL Scripting让整个管道保持在SQL中,降低SQL原生团队的学习门槛。

  • Python Data Source API——纯Python自定义数据连接器:完全用Python构建自定义、可重用的数据连接器,无需Java或Scala代码。支持谓词下推和模式推断,参与Spark查询优化。此前仅有Python客户端的数据系统或缺乏Java/Scala专业知识的团队无法为Spark构建自定义连接器。

  • transformWithState API——可查询的结构化流式状态:Spark 4.0的transformWithState API实现确定性计时器执行(按计划触发而非依赖数据到达)、自动状态TTL(防止无限增长)、模式演变(无需从新检查点重启)和状态可观测性(外部系统可读取运行中流式作业的实时聚合状态)。此前流式状态被锁定在运行的作业内,检查需要停止流或手动解析检查点文件。

  • emr-spark-8.0运行时栈:Apache Spark 4.0 + Apache Iceberg 1.10 + Apache Hudi 1.0.2 + Delta Lake 4.0 + Amazon DynamoDB/Kinesis/Redshift/S3连接器。简化的补丁管理:指定emr-spark-8.0.x时EMR自动选择最新补丁版本。Python 3.11默认(3.12/3.13可选),Java 17默认(21可选),Scala 2.13。AWS SDK for Java v2替代v1,EMR S3A连接器替代EMRFS。

行业影响

AWS Spark 4.0 GA的深层意义不是”又一个云平台支持新版本Spark”,而是Spark 4.0三大范式变革在最大规模部署平台上的生产就绪标志。

Spark 4.0引入的VARIANT、Spark Connect和SQL Scripting代表了Spark自3.0以来最重要的架构变革——半结构化数据处理从”字符串解析”走向”二进制列式”,开发体验从”打包部署”走向”本地远程”,ETL表达从”SQL+Python混合”走向”纯SQL”。这些变革在Databricks Runtime 18中已经以平台特定方式落地(Vol.7报道的SDP/RTM/SQL Scripting),但EMR GA意味着这些能力不再绑定于单一商业平台——任何使用EMR的组织都可以在托管环境中获得这些能力。

Spark Connect on EMR Serverless尤其值得关注。Spark的开发体验长期落后于DuckDB等轻量级引擎——DuckDB可以直接在Jupyter中import duckdb并查询数据,而Spark开发者需要先启动集群、配置环境、打包代码。Spark Connect消除这个差距:本地IDE中编写PySpark,远程EMR Serverless集群执行。当开发体验和生产执行使用同一后端时,“在开发阶段而非部署后捕获问题”从理想变为现实——这与Vol.13报道的Databricks Lakebase数据库分支的CI/CD集成方向一致,但Spark Connect的路径更轻量(无需创建分支,直接远程调试)。

emr-spark-8.0运行时捆绑Iceberg 1.10/Delta 4.0/Hudi 1.0.2是另一个重要信号。此前EMR对开放湖格式的支持通常滞后于最新版本(例如EMR 7.x捆绑的是较早版本的Iceberg/Delta/Hudi),emr-spark-8.0将三者同步推至最新意味着AWS对开放表格式生态的投入在加速——这与Vol.12报道的Databricks Iceberg v3 GA和Vol.16报道的Snowflake Interoperable Lakehouse共同推动的”开放湖仓”趋势一致。

相关链接


AWS Iceberg V3 VARIANT详解:半结构化数据从文本到二进制列式的三步走终点

事件概述

6月9日,AWS发布”Iceberg V3中的VARIANT数据类型实现”技术博客(两部分系列的第一部分),详细阐述了VARIANT在Amazon EMR上的首个生产实现。文章展示了如何在EMR Serverless上创建Iceberg V3表、插入VARIANT列数据、使用variant_get()查询特定字段。这是继Vol.7报道Iceberg 1.11.0定义VARIANT规范、Vol.12报道Databricks平台宣布Iceberg v3 GA后,VARIANT在云端生产环境的首次完整工程实现公开。

VARIANT在Parquet中的存储方式是其核心工程创新:三部分组合——binary metadata(包含类型和字典信息)、binary value(完整variant用于回退)、typed_value group(单个JSON字段被分解为独立的Parquet类型子列)。查询特定字段时,Spark仅修剪typed_value group中包含该字段的子列,同时始终保留metadata和value回退——这意味着查询无需加载或解析文档的其余部分。

技术解析

  • VARIANT的Parquet存储结构——列式裁剪替代全文档解析:VARIANT在Parquet文件中存储为三部分的struct。写入时,parse_json()将JSON字符串转换为二进制VARIANT格式,引擎可以分解结构将单个字段提取为typed_value group内的原生Parquet类型子列(如INTEGER、DOUBLE、STRING),未分解的字段保留在binary value列中作为回退。查询时,variant_get(variant_column, ‘$.path.to.field’, ‘type’)指定字段路径和返回类型,Spark仅读取包含该字段的子列而跳过其余部分。这比传统方案(将JSON存储为STRING,每次查询时用get_json_object解析)在两方面更优:查询处理时间减少(仅访问所需子列无需反序列化整个文档),存储占用降低(二进制编码比原始文本压缩效率更高)。

  • 与Vol.7/12的VARIANT进展对比:Vol.7报道的Iceberg 1.11.0定义了VARIANT的规范层面——File Format API插件模型、Deletion Vectors、Variant shredding的规范设计。Vol.12报道的Databricks Iceberg v3 GA宣布VARIANT在Databricks平台上的全面支持(托管表/外部表/UniForm表)。本期AWS EMR生产实现是第三步:在Parquet文件格式层面展示VARIANT的实际存储工程——typed_value group如何将嵌套JSON拆解为独立列、variant_get()如何利用列式裁剪跳过不相关数据、Glue Data Catalog如何管理VARIANT列的元数据。从规范到平台支持到云端生产,VARIANT完成了完整的落地路径。

  • Glue Data Catalog集成:使用AWS Glue Data Catalog作为Iceberg的目录实现(GlueCatalog),通过S3FileIO管理表数据在S3上的存储。创建Iceberg V3表时设置TBLPROPERTIES(‘format-version’ = ‘3’)启用VARIANT支持。这意味着VARIANT列的元数据(列定义、类型信息)被Glue Data Catalog统一管理,可在Athena/Redshift Spectrum/EMR等AWS分析服务间共享。

  • 当前限制:AWS Lake Formation的细粒度访问控制(FGAC)目前不支持VARIANT数据类型——无法对VARIANT列设置列级和行级权限。此外,运行此解决方案会产生EMR Serverless、S3和Glue的费用。

行业影响

AWS Iceberg V3 VARIANT生产实现的深层意义不是”又一个云平台支持VARIANT”,而是半结构化数据在数据湖中的存储范式从’文本编码’到’二进制列式编码’的最终落地。

此前数据湖中的JSON/半结构化数据面临三选一的困境:预先定义模式(数据演变时管道破裂)、存储为字符串(每次查询重型解析)、宽表设计(浪费存储)。VARIANT提供第四条路径:保持嵌套结构但使用二进制编码+列式裁剪——数据保持灵活(无需预定义模式),查询高效(仅读取所需子列),存储紧凑(二进制编码比文本压缩更优)。

typed_value group的设计精巧之处在于它不是简单的”JSON→Parquet”映射,而是”选择性列式化”——引擎可以选择性地将高频查询的字段分解为独立Parquet列,低频字段保留在binary value中作为回退。这种”冷热分层”思路与LSM-Tree的分层存储、KVCache的分层池化(Vol.19报道的华为云AMS)方向一致:热数据走快速路径(独立列直接读取),冷数据走兼容路径(全文档回退解析)。

将二十期主线串联,VARIANT的落地是”数据编码效率”主线的最新进展:Vol.7/12的Iceberg规范定义了VARIANT应该做什么,本期EMR生产实现展示了VARIANT实际怎么做。当半结构化数据不再需要”全文档解析”时,数据湖处理JSON的范式从”先解析后查询”走向”先列化后裁剪”——这与Vol.13报道的DuckDB-Iceberg扩展的MERGE INTO(从”能读Iceberg”到”能完整操作Iceberg”)方向一致:工具链正在从”能处理半结构化数据”走向”能高效处理半结构化数据”。

相关链接


Medium特征存储重设计:数据模型即瓶颈,从关系型90%浪费到列表型单分区直达

事件概述

6月9日,The New Stack报道Medium工程团队对其特征存储(Feature Store)数据模型的重设计——从关系型特征模型迁移到列表型特征模型,并在ScyllaDB上实现每秒100万次读取操作。原关系型特征模型将数据分割到两个表中(一个存储实体ID一个存储对应值),导致90.2%的读取行被直接丢弃、获取1000个实体值需要先查ID再逐个查值共1000次查询、过度依赖Cassandra的ALLOW FILTERING。新列表型特征模型将所有数据整合到单分区(以feature_key+entity_id为分区键、timestamp DESC+MD5(value)为聚类键),一次查询获取完整数据,行读取浪费从90.2%降至接近0%。

迁移到ScyllaDB后性能显著提升:Get List Items操作P50延迟从DynamoDB的3.5ms降至1ms,P99从70-220ms降至约30ms;Add List Items操作P50从5ms降至1.5ms以下,P99从40-120ms降至个位数毫秒。Medium工程总监Andréas Saudemont的总结直击要害:“如果你有一个次优的数据模型,你会有查询缓慢且扩展性差的问题。最有可能的是,你无法优化该数据模型。你必须定义一个更好的新数据模型。”

技术解析

  • 关系型特征的瓶颈——‘先查ID再查值’的二次查询模式:Medium原关系型特征模型将数据分割到两个表中——一个表存储实体ID(如用户阅读过的文章列表),另一个表存储对应的值。获取特征值需要两步:先查ID表获取实体列表(不含值),再对每个实体ID查值表。如果有1000个实体ID就需要1000次查询。同时关系型特征高度依赖Cassandra的ALLOW FILTERING(允许对非分区键/聚类键列进行过滤),监控数据显示90.2%的读取行被直接丢弃——这意味着查询效率极低,大量无用数据被读取后立即抛弃。

  • 列表型特征的设计——单分区’一次查询直达’:新模型的核心设计是将同一列表的所有项保存在一个分区中。分区键为feature_key+entity_id(如用户123的reading_history特征),聚类键为timestamp DESC+MD5(value)(按时间降序排列,MD5处理相同时间戳的多个不同值避免主键冲突)。获取特征值只需一次单分区查询:SELECT * FROM list_items WHERE feature_key = ? AND entity_id = ? AND timestamp >= ? LIMIT ?。聚类键直接处理过滤和排序,无需后处理。

  • TTL成本控制——自动过期替代清理逻辑:每行根据自身时间戳+特征TTL自动过期,无需手动清理逻辑。在稳定写入速率下,存储使用量达到平台期(新增和过期平衡)。特征退役时数据自动随时间消失。这与Vol.8报道的Databricks Predictive Optimization(自动优化存储)方向一致——运维负担从人工操作走向内置机制。

  • ScyllaDB vs DynamoDB——延迟可预测性的价值:ScyllaDB在所有延迟百分位上都优于DynamoDB(P50: 1ms vs 3.5ms,P95: 5-6ms vs 30-60ms,P99: ~30ms vs 70-220ms),但更关键的是延迟的可预测性——ScyllaDB的P99约30ms而DynamoDB的P99波动范围达70-220ms。Saudemont的评价是”ScyllaDB非常快速,性能非常可预测,这对我们来说至关重要”。注意DynamoDB未配置额外缓存层,可能通过缓存改进性能。

  • 按值删除——本地二级索引的巧妙使用:值不在主键中无法直接过滤,解决方案是创建本地二级索引CREATE INDEX idx_value ON list_items(value)。两步操作:先通过索引查找匹配的项键,再批量删除。选择本地索引而非全局索引是因为查询高度选择性(列表中很少有相同值的项),本地索引比全局索引更快。

行业影响

Medium特征存储重设计的深层意义不是”又一个ScyllaDB迁移案例”,而是数据模型选择对系统性能和扩展性的决定性影响——这不是’调优’问题而是’架构’问题。

Saudemont的核心论点值得每个DataInfra从业者深思:“如果你有一个次优的数据模型,你会有查询缓慢且扩展性差的问题。最有可能的是,你无法优化该数据模型。你必须定义一个更好的新数据模型。所以在开始实现之前,花时间思考你的数据模型,因为一旦你有使用次优数据模型的生产数据,就太晚了。“这不是性能调优建议而是架构决策建议——当90.2%的读取行被直接丢弃时,问题不在查询优化器、不在缓存层、不在硬件配置,而在数据模型本身。

将本期三条动态串联,三者都在消除数据路径上的”多余解码和多余读取”:Spark 4.0 VARIANT将半结构化数据从”文本字符串”推进到”二进制列式编码”(消除JSON文本解析的开销),Iceberg V3 VARIANT在Parquet中实现typed_value组裁剪(消除全文档加载和全文档解析),Medium特征存储将数据模型从关系型”二次查询”推进到列表型”单分区直达”(消除无效行读取和多轮查询)。三者分别从编码格式、存储布局和数据模型三个层面优化数据路径效率——当数据路径上的每一层都消除”多余”时,端到端的查询性能提升不再是线性的而是指数级的:Medium案例中从90.2%行浪费+1000次查询到接近0%浪费+1次查询,性能提升不是10%或50%而是数量级的。

相关链接


编者评

第二十一期的三条动态,从三个不同层面共同指向数据基础设施的”编码效率”主线——消除数据路径上的”多余解码和多余读取”。

第一个层面是编码格式:Spark 4.0 VARIANT将半结构化数据从文本推进到二进制列式。 此前数据湖中的JSON数据要么存储为字符串(每次查询全文档解析),要么预先定义模式(数据演变时管道破裂)。VARIANT的parse_json()→variant_get()路径让JSON数据在写入时即被二进制编码,查询时按字段路径裁剪——从”先读全部再解析”走向”只读需要的”。这与Vol.7报道的Iceberg 1.11.0 VARIANT规范和Vol.12报道的Databricks Iceberg v3 GA形成完整的落地路径:规范定义了”应该做什么”,Databricks平台展示了”可以做什么”,AWS EMR生产实现证明了”实际怎么做”。

第二个层面是存储布局:Iceberg V3 VARIANT的typed_value组实现选择性列式化。 VARIANT在Parquet中不是简单的”JSON→Parquet”全量映射,而是”选择性列式化”——高频查询字段被分解为独立Parquet列走快速路径,低频字段保留在binary value中走兼容路径。这种冷热分层思路与LSM-Tree分层存储、KVCache分层池化(Vol.19报道的华为云AMS)方向一致:不是所有数据都需要同等待遇,按访问模式分层是提升效率的通用策略。当VARIANT的生产实现消除了”全文档解析”的必要性时,数据湖处理半结构化数据的范式从”先解析后查询”走向”先列化后裁剪”。

第三个层面是数据模型:Medium特征存储从关系型’二次查询’到列表型’单分区直达’。 90.2%行浪费和1000次查询不是调优问题而是架构问题——关系型特征模型的数据分割(ID表+值表)迫使查询走”先查ID再逐个查值”的低效路径。列表型特征模型通过分区键设计(feature_key+entity_id)让一次查询获取完整数据。Saudemont的总结——“一旦你有使用次优数据模型的生产数据,就太晚了”——对DataInfra从业者是最直接的警示:数据模型的选择决定系统的性能上限,后续的优化只能逼近而不能超越这个上限。

将二十一期主线串联,数据基础设施的效率优化正在从’运行时优化’走向’编码层优化’。 此前二十期的动态主要集中在运行时层面:查询优化器改进、执行引擎加速、缓存策略优化。本期三条动态表明,效率优化的焦点正在前移到编码层——数据在写入时就决定了后续查询的效率上限。VARIANT的二进制编码在写入时完成JSON→二进制的转换(消除查询时的解析开销),typed_value组在写入时完成选择性列式化(消除查询时的全文档加载),列表型特征在写入时完成分区设计(消除查询时的多轮请求)。当数据在写入时就被编码为最高效的查询格式时,‘写入一次,高效查询多次’从理想变为现实——这比任何运行时优化都更根本,因为它改变了数据的初始状态而非处理数据的方式。