EMR Serverless Spark AI Function 的双维降本实践

引言

EMR Serverless Spark AI Function 自推出以来,已在智能智驾、具身智能、互联网等多个行业落地,服务了大批生产客户。在此前的内容中,我们介绍了 AI Function 的基本用法与核心能力;本篇作为延续,进一步解读并发控制、算子下推等执行机制,并聚焦一个随数据规模增长愈发关键的问题:如何控制 AI 任务的整体计算成本。

一项大规模 AI 任务的成本主要来自两部分:调用模型产生的推理费用,以及运行 Spark 作业产生的计算资源费用。围绕这两类成本,本文介绍两个作用于不同维度的降本手段------感知 AI Function 的查询优化(减少真正进入模型的调用量)与 Batch File 异步批量推理(以更低的单位价格执行推理,并释放等待阶段的计算资源),并说明它们各自的适用场景与叠加方式。

任务总成本 ≈ 模型推理成本 + Spark 计算成本

模型推理成本 ≈ 有效调用量 × 单次平均 Token × 模型单位价格

Spark 计算成本 ≈ 活跃计算资源规模 × 活跃时长 × 资源单价

降本维度 代表能力 适用范围 主要价值
减少有效调用量 AI 查询优化 在线模式与 Batch File 模式 过滤无效数据,避免重复调用
降低模型单价与计算成本 Batch File 异步批量推理 对时延不敏感的离线任务 使用批量价格,收缩等待阶段的 Executor

大规模 AI 任务的成本为什么容易失控

在普通 Spark 查询中,过滤、投影、聚合等本地算子的单位成本相对稳定,优化器通常关注扫描量、Shuffle、Join 策略和数据倾斜。AI 函数却改变了成本结构:一次远程模型调用的延迟和价格,可能远高于同一行上的本地表达式计算;如果计算节点还需要长时间等待远端结果,Spark 资源费用也会随等待时间继续累积。

这意味着,大规模 AI 任务的成本治理至少要回答三个问题:实际需要调用多少次模型、每次调用以什么方式计费,以及 Spark 计算资源需要活跃多久。 两个逻辑等价的执行计划,最终的 AI 调用量可能相差几个数量级;同样一批请求,在线与 Batch File 不仅面向不同的时延目标和模型价格,也会形成不同的计算资源占用方式。

例如:

sql 复制代码
SELECT
  review_id,
  ai_sentiment(review_text) AS sentiment
FROM reviews
WHERE review_date >= '2026-01-01'
LIMIT 1000;

这条 SQL 不会"先推理全量再截取 1000 行"------Spark 会先用日期条件缩小范围,也会在拿到足够结果后停止处理。但在分布式执行中,系统仍可能提前准备候选数据,导致少量已推理的行未进入最终结果。对本地计算这微不足道,对模型调用则意味着多余的 Token 和费用。查询优化会尽量先确定真正需要的 1000 条数据再推理,让调用量更贴近最终结果规模。

因此,适用范围最广的降本动作不是"把请求发得更快",而是:先确认哪些请求根本不需要发送。

降本维度一:用 AI 查询优化减少调用量

AI 查询优化让 Spark 在计划阶段识别 AI 表达式,意识到"Project 通常是轻量本地计算"的假设不再成立,从而在保证结果语义的前提下,把便宜、确定的数据缩减尽量安排在模型调用之前。下文选取 Filter 前置、Limit 与排序协同、输入去重三类典型场景说明优化思路;引擎还内置了更多 AI 查询优化规则,能根据实际 SQL 自动协同生效。

2.1 复杂表达式下的 Filter 前置:先缩小数据,再推理

大模型调用受采样和服务状态影响,同一输入不保证每次结果相同,因此 EMR Serverless Spark 按非确定性语义处理 AI Function,避免通用规则随意重排模型调用。但这也意味着:当普通计算与 AI Function 出现在同一层时,原生 Spark 往往不会让 Filter 穿过混合计算,即使过滤条件完全不依赖模型结果。

下面这个例子中,过滤条件依赖新生成的 normalized_text,但不依赖 AI 返回的 sentiment

sql 复制代码
SELECT
  normalized_text,
  sentiment
FROM (
  SELECT
    upper(review_text) AS normalized_text,
    ai_sentiment(review_text) AS sentiment
  FROM reviews
) enriched
WHERE normalized_text LIKE '%REFUND%';

AI 查询优化器能识别过滤条件与模型结果之间的依赖关系,先生成标准化文本并完成过滤,再仅对保留下来的行做情感分析。如果过滤后只剩 20% 的数据,AI 调用量也随之缩小到约 20%。反之,如果过滤条件引用了 AI 结果(如 sentiment = 'negative'),过滤就不能越过对应的 AI 计算。

2.2 Limit 与排序协同:重新权衡短路与推理成本

需要区分单独 LIMITORDER BY ... LIMIT 两类场景。对于没有排序的 LIMIT 1000,Spark 本身会在拿到足够结果后停止处理,但分布式执行中仍可能提前准备候选数据,造成少量额外调用;查询优化会尽量先确定真正需要的数据,让调用量进一步贴近 1000。

带排序的 Limit 优化空间更大。例如"按评论时间取最新 1000 条再做情感分析",只要排序键不依赖 AI 结果,引擎就可以先完成排序与裁剪,再只对最终 1000 行调用模型。但如果查询要求"按 AI 评分排序后取前 1000 条",所有候选行的评分都可能影响排名,此时不能把 LIMIT 提前------查询优化遵循的首要原则仍是保持 SQL 语义

下图以一条带 LIMIT 10 的查询为例,展示了优化前后的执行计划与 AI 指标对比:

未优化时,AIProject 位于 CollectLimit 之前,引擎先对 26 行候选数据逐一调用模型,再截取最终 10 行;开启查询优化后,GlobalLimit 被推至 AIProject 之前,仅对最终需要的 10 行执行推理。对应地,number of AI requests 从 26 降至 10,number of AI input tokens 从 65,572 降至 25,220,AI 请求耗时从 1.6 分钟缩短至 28.8 秒。这些指标(请求数、Token 用量、限流重试次数等)是 EMR Serverless Spark 在原生 Spark UI 基础上新增的 AI 可观测维度,用户无需额外埋点即可在作业详情中直接观察优化效果。

2.3 输入去重:相同问题只问一次

真实数据中经常存在大量重复输入,例如模板好评、重复工单、批量复制的商品描述。当同一个 AI 函数以相同参数处理相同输入时,引擎可以只计算一次,再把结果复用到对应行。"相同输入"指完整的 AI 调用语义一致------函数类型、模型服务、标签集合和推理选项都相同,结果才会复用。去重本身有额外的数据组织和结果回填开销,因此更适合重复率较高、单次调用较贵的数据集。

2.4 不止三个示例,而是一套优化体系

上述三个场景是优化思路的代表性切面,并非完整列表。EMR Serverless Spark 已围绕表达式依赖、数据缩减、结果复用和复杂查询协同等方面构建了一整套 AI 查询优化规则,可以单独生效,也可以在一条 SQL 中协同工作,但都遵循同一条原则:

在不改变查询语义的前提下,让尽可能少的数据到达 AI 计算节点。

用户看到的仍是一条普通 SQL,不需要为了节省调用而手工拆分任务或维护中间表。

查询优化回答了"能不能少调一些",无论后续采用在线还是离线执行都能产生收益。对于必须尽快返回的任务,优化后的请求继续走在线模式;而对于能够接受非实时完成的任务,还可以进一步追问:剩下这些调用,能否用更具性价比的批量方式完成?

降本维度二:接受非实时,用 Batch File 降低模型与计算成本

3.1 Batch File 适合解决什么问题

阿里云百炼 Batch File API 面向对时延不敏感的大规模推理任务,采用异步批处理范式:先提交一批请求,由服务端在完成窗口内处理,再统一获取结果。与实时 API 的"发送一个请求、等待一个响应"不同,它把推理从同步调用变成了后台任务。

但把这套异步批处理能力接入 Spark,并不只是把多行请求拼成一个文件。批量任务可能需要较长时间才能完成;如果 Spark Task 在此期间一直占用 Executor 轮询,即使模型调用价格降低,等待过程仍会带来持续的计算资源开销。要同时降低两类成本,关键是让 Spark 计算资源不必陪着远程任务一起等待。

因此,对于离线数据管线,这种模式会同时影响两张账单:

  • 模型推理费用更低:Batch 推理通常按对应实时模式价格的 50% 计费,具体支持范围和价格以百炼最新计费说明为准;

  • Spark 计算资源费用更低:异步提交完成后,Executor 不需要持续占用来等待模型结果;在 Serverless 资源策略允许时,可以收缩执行计算资源,结果就绪后再恢复计算。

3.2 异步 Batch 的三个阶段

EMR Serverless Spark AI Function 的异步 Batch 执行包含如下三个阶段:

  1. 提交:Spark 读取输入数据,生成批量请求并提交给模型服务,同时保留后续恢复结果所需的关联信息;

  2. 等待:提交完成后释放执行计算节点,由轻量的任务协调逻辑跟踪批量任务状态;

  3. 回收:模型服务完成推理后,Spark 恢复计算,拉取结果并与原始记录对齐,继续执行后续 SQL。

这套机制的关键价值不是"让模型更快返回",而是把远端服务的等待时间与 Spark 计算资源解耦。在异步模式下,Executor 不需要为了轮询状态持续占用;工作空间能否缩容以及最终资源费用,仍取决于用户的 Serverless 资源策略和作业中的其他活动阶段。

状态恢复、失败处理和结果对齐由引擎统一管理。对用户来说,Batch File 仍然只是同一条 SQL 的一种执行方式,不需要额外编写上传文件、轮询任务和回填结果的脚本。

3.3 在非实时场景中,两个降本维度如何叠加

查询优化与 Batch File 可以分别使用,也可以同时生效。查询优化属于通用能力,在线与离线任务都可以受益;Batch File 则适用于业务能够接受非实时返回的离线任务。

当任务同时具备离线、规模大、成本敏感这三个特征时,两项能力可以自然叠加:只开启 Batch,仍可能把大量本可过滤或去重的数据送进模型;先通过查询优化缩减调用,再进入 Batch,才能同时降低调用量和单位价格。

在这种离线场景下,执行路径是:

  1. 普通 Spark 算子先完成扫描裁剪、过滤、排序和必要的数据缩减;

  2. 查询优化进一步减少真正需要推理的行和重复输入;

  3. 剩余请求再进入异步 Batch,以更低的单位价格处理;

  4. 结果返回 Spark,继续参与后续投影、写表和分析。

两项能力共同服务于"降本",但适用范围与作用维度不同:查询优化负责减少调用量;Batch File 在业务接受非实时的前提下,进一步降低模型单价和计算资源成本。

实战:500 万条电商评论的双维降本

下面选择一个明确允许非实时完成的离线场景,把两项能力串起来。示例数字用于说明计算方法,不代表固定的产品性能或价格承诺。

4.1 业务背景

某电商平台在 Paimon 表中积累了 500 万条用户评论。数据团队希望完成三类标注:

  • 情感倾向:正面、负面、中性;

  • 问题分类:物流、质量、价格、服务等;

  • 关键实体:商品名称、缺陷类型、配送时长等。

结果会写入下游分析表,用于品类洞察、客户体验分析和客服工单路由。

传统 Python 脚本不仅需要逐条调用模型,还要自行实现并发控制、限流退避、失败重试、断点续传和结果落盘。数据规模越大,这些非业务代码越容易成为主要维护成本。

4.2 用户看到的仍然是一条 SQL

sql 复制代码
-- 启用 Batch File,并使用可释放 Executor 的异步模式
SET spark.emr.serverless.ai.batchFile.enabled = true;
SET spark.emr.serverless.ai.batchFile.mode = async;

-- 数据中存在较多模板评论时启用输入去重
SET spark.emr.serverless.ai.deduplicate.enabled = true;

WITH enriched_reviews AS (
  SELECT
    review_id,
    review_text,
    to_date(review_time) AS review_date,
    lower(trim(product_category)) AS normalized_category,
    ai_sentiment(review_text) AS sentiment,
    ai_classify(
      review_text,
      ARRAY('物流问题', '质量缺陷', '价格争议', '服务态度', '正面好评')
    ) AS issue_category,
    ai_extract(
      review_text,
      ARRAY('product_name', 'defect_type', 'delivery_days')
    ) AS entities
  FROM ods_user_reviews
)
INSERT INTO review_labels
SELECT
  review_id,
  normalized_category AS product_category,
  review_text,
  sentiment,
  issue_category,
  entities
FROM enriched_reviews
WHERE review_date >= '2026-01-01'
  AND normalized_category IN ('electronics', 'home_appliance');

这条 SQL 在 CTE 中完成日期转换、品类标准化和三项 AI 标注,后续 Filter 只依赖普通派生列;执行模式、恢复流程和并发细节由引擎统一管理。

4.3 调用量是怎样降下来的

假设示例数据符合以下分布:

阶段 数据量 说明
原始评论 500 万行 混合计算的全量候选数据
日期与品类过滤后 120 万行 查询优化将不依赖模型结果的 Filter 前置
去除重复 AI 输入后 85 万条唯一输入 模板评论只推理一次
三个 AI 函数的最终调用量 255 万次 85 万 × 3

在这个混合表达式场景中,如果没有查询优化,包含非确定性 AI 调用的整体计算无法被简单拆分,500 万行数据都可能先进入三个 AI 函数,潜在调用量为 1500 万次。查询优化在确认过滤条件不依赖模型结果后,先将数据收缩到 120 万行,再结合输入去重收敛到 85 万条唯一输入。三个 AI 函数最终只需约 255 万次调用,降到未优化基线的 17%,即减少约 83%。

4.4 两个降本维度如何叠加

为了避免不同模型之间的价格差异影响比较,下面采用相对成本进行估算:

查询优化后的调用量系数 = 255 万 / 1500 万 = 17%

Batch 单位价格系数 = 50%

相对推理成本 = 17% × 50% = 8.5%

在单次平均 Token 基本相同的前提下,组合方案的模型推理费用约为"全量实时逐行调用"的 8.5%,对应约 91.5% 的理论降幅。

上述估算仅覆盖模型推理费用;Spark 计算侧的收益取决于资源规格与伸缩策略,需结合实际作业单独评估。

4.5 方案对比

维度 自建 Python 调用脚本 在线 AI Function + QO 异步 Batch File + QO
开发方式 自行编排 API 与状态 SQL / DataFrame API SQL / DataFrame API + 执行配置
示例 AI 调用量 取决于脚本是否主动过滤与去重 约 255 万次 约 255 万次
模型单位价格 实时价格 实时价格 通常为对应实时价格的 50%
远端等待期 脚本进程持续管理 Executor 参与在线执行 异步模式可释放 Executor
限流与重试 用户自行实现 引擎统一处理 引擎统一处理
任务恢复与结果对齐 用户自行实现 引擎统一处理 引擎统一处理
适合场景 小规模定制流程 低延迟、交互式或持续到达的数据 大规模、离线、成本敏感任务

如何开启与调优

白名单说明:Batch File 异步批量推理功能当前处于白名单测试阶段,如需使用请联系 Serverless Spark 团队申请开通。

5.1 最小配置

如果目标是使用异步 Batch 并在等待阶段释放 Executor,需要同时开启 Batch File 和异步模式:

sql 复制代码
SET spark.emr.serverless.ai.batchFile.enabled = true;
SET spark.emr.serverless.ai.batchFile.mode = async;

如果数据重复率较高,再开启输入去重:

sql 复制代码
SET spark.emr.serverless.ai.deduplicate.enabled = true;

5.2 按 AI Function 选择执行模式

会话级配置适合整段作业采用统一策略。如果只希望为某个 AI Function 开启 Batch File,或者需要为不同处理阶段分别选择 Batch File 的同步、异步模式,也可以通过函数的 options 参数设置 batch_mode

sql 复制代码
-- 为该 AI Function 选择异步 Batch File 模式
SELECT
  review_id,
  ai_sentiment(
    review_text,
    options => '{"batch_mode":"async"}'
  ) AS sentiment
FROM reviews;

batch_mode 可以设置为 "sync""async";设置为 true 时,则启用 Batch File 并沿用会话默认模式。实际使用时,建议同一个 SELECT 投影中的多个 AI Function 保持一致的 batch_mode;如果它们的时延要求不同,可以拆分为不同处理阶段。

多模态数据当前不支持 Batch File 当前 Batch File 模式暂不支持多模态数据,包括携带图片等多模态输入的 ai_queryai_embedding_multimodal。这类调用会使用在线模式;如果它们与文本 AI Function 出现在同一个 SELECT 投影中,该投影也会整体按在线模式执行。建议将文本离线推理与多模态处理拆分为不同阶段。

5.3 常用参数

sql 复制代码
-- 单个批量文件的最大请求数,当前默认值为 10000
SET spark.emr.serverless.ai.batchFile.maxRequestsPerFile = 10000;

-- 批量任务完成窗口,当前默认 24h,可在支持范围内调整
SET spark.emr.serverless.ai.batchFile.completionWindow = 24h;

参数并不是越大越好。文件过大会拉长单个批次的恢复粒度,过小则增加任务和文件数量;完成窗口应根据业务 SLA 选择。

5.4 PySpark DataFrame API

python 复制代码
from emr_serverless_spark_ai import ai_sentiment, ai_classify
from pyspark.sql.functions import col

spark.conf.set("spark.emr.serverless.ai.batchFile.enabled", "true")
spark.conf.set("spark.emr.serverless.ai.batchFile.mode", "async")
spark.conf.set("spark.emr.serverless.ai.deduplicate.enabled", "true")

reviews = spark.table("ods_user_reviews")

result = reviews.select(
    col("review_id"),
    ai_sentiment(col("review_text")).alias("sentiment"),
    ai_classify(
        col("review_text"),
        ["物流", "质量", "价格", "服务"],
    ).alias("category"),
)

result.write.mode("overwrite").saveAsTable("review_labels")

SQL 与 DataFrame API 共用同一套执行与优化能力,团队可以按现有工程习惯选择接口。

选型建议:什么时候用在线,什么时候用 Batch

Batch File 不是在线模式的替代品,两者面向不同的延迟目标。

判断问题 更适合在线模式 更适合异步 Batch File
用户是否正在等待结果?
是否要求秒级或分钟级响应? 否,允许完成窗口
数据是否持续到达? 流式或持续到达 有明确批次边界
任务规模 小到中等、重视即时性 大规模、重视吞吐与成本
计算资源是否可在等待期缩容? 通常不关注 希望释放 Executor
典型场景 交互式分析、在线服务、实时辅助 T+1 打标、历史回填、离线 ETL、周期性内容处理

还有两个容易忽略的边界:

  • 查询优化不只服务于 Batch。 Filter、Limit 等调用削减能力对在线模式同样有效;

  • 并非所有输入形态都适合 Batch。 例如多模态请求涉及媒体读取和有效期管理,当前会使用在线执行。具体函数与模型支持范围应以实际测试为准。

总结

EMR Serverless Spark AI Function 把大模型能力带入用户熟悉的 SQL 与 DataFrame 工作流,同时让 Spark 能够理解 AI 调用是一种昂贵、需要治理的外部计算。面对不断增长的数据规模,降本需要同时关注模型服务和 Spark 计算两张账单:调用多少次、以什么价格调用,以及计算资源需要活跃多久。

本文介绍的两个降本维度分别解决了不同问题,也有不同的适用边界:

  • AI 查询优化通过 Filter、Limit、输入去重等手段,在计划阶段减少不必要的模型调用,在线与离线任务都可以受益;

  • Batch File 异步批量推理面向能够接受非实时完成的离线任务,用更具性价比的执行方式处理请求,并将远端等待与 Executor 资源占用解耦。

对于时延敏感任务,在线 AI Function 加查询优化就是完整方案;对于成本敏感的离线任务,则可以在此基础上选择 Batch File,形成"先减少调用,再降低模型单价与计算资源成本"的组合优化路径。

对数据团队而言,真正有价值的不只是把几段 API 调用改写成一条 SQL,而是把过去散落在脚本中的并发、限流、恢复、成本和资源问题,收敛为平台能够统一优化和治理的数据处理能力。这也是 Serverless Spark 从"大数据计算引擎"走向"AI 原生数据处理平台"的关键一步。

相关推荐
维基框架3 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab3 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能
AKAMAI3 小时前
你的源服务器可能是你做出的最昂贵决定
运维·人工智能·云计算
冬奇Lab4 小时前
【无标题】
人工智能·开源
专业贴准4 小时前
苏州SMT供料器设备选型分析:本地主流自动化企业技术特点与行业趋势
人工智能·自动化·制造
cxr8284 小时前
Synapse Mind (三维智能认知图谱) 全景深度工程
人工智能·交互·智能体·认知框架
维基框架4 小时前
OpenAI在给Git做优化 上游行为要变了
人工智能·git
1名持续学习的码农4 小时前
GPT Plus、GPT Pro用户第一次用Codex,项目权限和Git分支怎么设置?
人工智能·git·gpt·elasticsearch·ai编程·codex