用 Codex + 阿里云 DataWorks MCP 实现数仓自动化

摘要:需求评审过了,口径也定了,接下来是真正的体力活------摸表、建表、接源表、配调度、提交发布、加工、对账。这一篇不讲怎么谈需求,只讲从需求定稿那一刻起,Codex + DataWorks MCP 是怎么把这条链路走完的;并在每一步给出「自己开发要做什么」的对照,最后落到价值。文中示例已脱敏,密钥只走环境变量。


0. 前提:本文从「需求已定」开始

需求确认这一步必须先做完,而且产出必须落到文档里。明确下面这些,才谈得上开工:

已定稿的输入 内容 谁给
指标与口径 一共几个指标、各自怎么算、剔除谁 业务 + 数据
粒度 明细到什么层级、榜单聚合到什么层级 业务
时间窗口 统计时间字段、半开区间 [start, end) 数据
单位 金额是分还是元、比率保留几位 财务
比较基准 「排名靠后」到底是跟谁比 业务
责任与时限 谁验收、什么时候上线 双方

这份清单就是后面所有工作的输入。 反过来说:如果这些还没定,后面的效率再高也只是更快地做错。

我们这次的例子:业务要一条链路,把 6 个指标(欠费、保证金、销售排名、客诉、私收银、诉讼)算到摊位粒度 ,用于月度招商调整。其中三个指标还在靠人每月手工导表------这就是要补的缺口。

先看清这条路是怎么运转的------它是这一篇所有步骤的底座:

图 1:Agent 的执行闭环。人描述目标,Agent 读知识、生成产物、调接口执行、读回执自查,最后把修正回写到仓库------所以下一轮会更快。


1. 第一件事:把定稿口径翻译成「建设清单」

1.1 定稿口径 → 交付物

交付物 形态 谁用
贴源表 ×3 三张源表的日分区全量 下游加工
ETL 任务 3 个同步任务 + 5 个加工节点 调度
调度依赖 上游同步 → 加工 → 榜单 调度
榜单表 ×1 摊位粒度、ds 快照 业务
对账项 行数 / 金额 / 主键三类 验收
文档 主题 README + 口语说明 后人

1.2 六问六答

清单里出现下面这些,必须确认清楚才能动手:

问题 为什么要问
主键是什么? 决定去重与唯一性约束
金额单位是分还是元? 决定要不要 /100,错了差 100 倍
统计时间用哪个字段? 支付时间 ≠ 下单时间,差一天就错一期
测试 / 虚拟 / 统计合并要不要剔? 不剔就会多算,且业务一眼看出来
上下游依赖是谁? 上游没到,跑出来就是「全是 0」的假数据
窗口是闭区间还是半开? 期末重复计数,金额差一天的量

这六个问题,Agent 答不了,但它能帮你问全。 这是它第一个价值点:把「老手才知道要问什么」变成「每次都会问全」。


2. 七步链路逐段走(每段都带自研对照)

图 2:需求定稿之后的七步链路。每一步的产物都落在仓库里;两个橙点是必须由人点头的地方。

① 摸家底:先知道有什么,再决定建什么

自己开发 Codex + DataWorks MCP
怎么查 打开控制台,翻数据地图 / 逐张表点开看字段 让 Agent 调只读接口拉项目、数据源、表与字段,或直接读仓库里的 reference.md
能查到什么 表名、字段、血缘(要一个个点) 同上,且一次把结果落盘成文件,可复用、可 diff
血缘 在界面上展开,看完就关掉 跑一遍脚本,产出 table_usage_rank.csv,可反复看
遗漏风险 靠经验,容易漏看同类表 全量扫,不靠记忆

我们的做法是先跑一遍血缘热度(工具在 tools/odps_lineage/):

text 复制代码
hot_score = downstream_count * 2 + upstream_count

结论直接改了方案:

发现 影响
日期维表被几乎所有任务引用 累计窗口直接复用,不自己造日期逻辑
已有摊位级欠费、保证金汇总表且热度很高 不新建同类表,直接 JOIN,避免两套欠费口径
客诉 / 诉讼没有对应表 确认为本次要新建的部分

自研和用 Agent 在这一步的差别不是「查得快不快」,而是「有没有查全」。 人查表会带着假设查,Agent 是全量列。

② 建表:DDL 一次写对,两套环境都能用

自己开发 Codex + DataWorks MCP
建表方式 控制台建表向导,字段一个个填类型和注释 Agent 生成 DDL,走 PyODPS 批量执行
字段数量 20 个字段要点 20 遍 一次生成
规范一致性 取决于当天状态 分区列固定 dsALIORC、生命周期按分层给,每次一样
sql 复制代码
CREATE TABLE IF NOT EXISTS ${project}.ods_cs_complaint (
    id               BIGINT   COMMENT '主键',
    booth_id         BIGINT   COMMENT '摊位ID',
    market_id        BIGINT   COMMENT '卖场ID',
    complaint_type   STRING   COMMENT '客诉类型',
    complaint_status STRING   COMMENT '工单状态(口径见README)',
    happen_time      DATETIME COMMENT '发生时间',
    close_time       DATETIME COMMENT '关闭时间',
    create_time      DATETIME COMMENT '创建时间'
)
COMMENT '客诉工单_贴源_日全量'
PARTITIONED BY (ds STRING COMMENT '日期分区,格式yyyyMMdd')
STORED AS ALIORC
LIFECYCLE 732;

贴源层的三条规矩(写进 Skill,Agent 每次都会带):

  1. 贴源层不加工,不改业务含义
  2. 分区列固定 ds,格式 yyyyMMdd
  3. 生命周期按分层给:贴源层给足,交易明细类可短一些

注释里那句「口径见 README」是有意写的:容易误解的字段,注释要留一个能继续查下去的入口。

③ 接源表:从「点向导」到「生成脚本 + 幂等执行」

这一步是自研与 Agent 差别最直观的地方。

自研怎么做: 新建离线同步任务,选源/目标数据源、选表、逐个字段点映射 、配切分键、配并发、配错误记录数、写目标分区......字段多的时候,一个任务点几十下;column 顺序错了还要重来。

Codex + MCP 怎么做: 把源表 DDL 和目标表 DDL 给 Agent,它生成 DataX 的 TaskContent,再由脚本建任务:

json 复制代码
{
  "steps": [
    {
      "stepType": "mysql",
      "parameter": {
        "datasource": "src_cs_db",
        "table": ["t_complaint"],
        "column": ["id","booth_id","market_id","complaint_type","complaint_status","happen_time","close_time","create_time"],
        "splitPk": "id"
      }
    },
    {
      "stepType": "odps",
      "parameter": {
        "datasource": "odps_first",
        "table": "ods_cs_complaint",
        "partition": "ds=${bizdate}",
        "truncate": true,
        "column": ["id","booth_id","market_id","complaint_type","complaint_status","happen_time","close_time","create_time"]
      }
    }
  ]
}
js 复制代码
// 幂等:同名任务存在就复用,避免重复创建
const exist = await client.listFiles(new sdk.ListFilesRequest({
  projectId: PROJECT_ID, exactFileName: TASK_NAME, fileTypes: '23',
}));
let fileId = exist?.body?.data?.files?.[0]?.fileId;
if (!fileId) {
  const resp = await client.createDISyncTask(new sdk.CreateDISyncTaskRequest({
    projectId: PROJECT_ID,
    taskType: 'DI_OFFLINE',
    taskName: TASK_NAME,
    taskContent: JSON.stringify(taskContent),
    taskParam: JSON.stringify({ FileFolderPath: FOLDER, ResourceGroup: DI_RG }),
  }));
  fileId = resp.body.data.fileId;
}
维度 自己开发 Codex + DataWorks MCP
操作形态 在界面上点 生成配置 + 调接口
字段映射 手点,几十下 从 DDL 生成,顺序天然一致
幂等 靠人记得先看有没有 脚本先查再建,天然幂等
记录 无(点完就没了) 配置 JSON 进 Git,可评审可复用

注意一个真实边界: 老版单表离线同步任务不在 MCP 工具面里,要走官方 SDK。这恰恰说明用法不是「非 MCP 不可」,而是:

MCP 能覆盖的由 Agent 直接调;覆盖不到的,用 SDK 补位------对使用者来说,都是「描述目标,Agent 执行」。

④ 配调度:业务依赖比参数更容易错

js 复制代码
await client.updateFile(new sdk.UpdateFileRequest({
  projectId: PROJECT_ID, fileId,
  cronExpress: '00 00 02 * * ?',      // 源库跑批结束后再取数
  cycleType: 'DAY',
  inputList: 'your_project_root',     // 上游依赖
  outputList: 'your_project.ods_cs_complaint',
  paraValue: 'bizdate=$bizdate',      // 与分区里的 ${bizdate} 是两处
  rerunMode: 'ALL_ALLOWED',
  resourceGroupIdentifier: SCHED_RG,  // 资源组标识,不是显示名
  schedulerType: 'NORMAL', stop: false,
}));
配置项 自己开发 Codex + DataWorks MCP
Cron 手敲,容易错位(0 0 2 * * ? vs 0 2 * * ? 生成后对照选项核对
依赖 在依赖树上拖 写成 inputList / outputList,可 review
调度参数 节点属性里填,容易忘 与分区参数一起被检查
资源组 下拉选,可能选错同名项 用资源组标识,明确

这一步最贵的错误不是参数写错,是依赖漏配。

上游数据没到、下游照样跑,跑出来是一个「客诉全是 0」的榜单------数字看着正常,实际上把商户的差评全洗白了。这类错误自研也常犯,区别在于:靠人工检查会漏,靠脚本检查不会。

⑤ 提交 → 发布 → 轮询:把「干等」变成「可追踪」

自研怎么做: 点提交 → 点发布 → 看发布记录等状态;发布是异步的,等的时候干别的,回头可能忘了看到底成没成。

Codex + MCP 怎么做: 三步一次跑完,并轮询到确定结果。

text 复制代码
SubmitFile → DeployFile → GetDeployment 轮询(status=1 成功 / status=2 失败)
维度 自己开发 Codex + DataWorks MCP
结果确认 靠记着回来看 轮询到确定状态才结束
失败处理 手工再点一次 记录失败项,支持断点重跑
批量 N 个任务 = N 遍点击 一次循环,失败项单独重试

还有一条硬事实:发布完成当天 02:00 之前不会自动生成实例,首个分区必须靠运维中心「补数据」。这件事自研时经常是「上线第二天发现昨天没数」才想起来的。

⑥ 加工层:把定稿口径写成 SQL

骨架由 Agent 出,口径由人定。我们这次最关键的两个加工点:

排名要与自己可比的比。 护肤品摊位和家具摊位比销售额,小品类永远垫底,所以排名按「同卖场 + 同品类」:

sql 复制代码
,ranked AS (
    SELECT
        booth_id, l2_category_id, sales_net
        ,PERCENT_RANK() OVER (
            PARTITION BY market_id, l2_category_id      -- 同卖场 + 同品类
            ORDER BY sales_net DESC
        ) AS rank_pct
        ,ROW_NUMBER() OVER (PARTITION BY booth_id ORDER BY sales_net DESC) AS cate_rn
    FROM sales_cate
    WHERE sales_net > 0                                  -- 无销售不参与排名
)
-- 分档:前 30% / 中 30% / 后 40%
CASE WHEN rank_pct <= 0.30 THEN 1 WHEN rank_pct <= 0.60 THEN 2 ELSE 3 END AS rank_bucket

综合评分要与排名档位对齐。 榜单说「前 30%」,评分表的销售分就得给满分,两套口径不一致,业务一定会来问:

sql 复制代码
,CASE WHEN COALESCE(rk.rank_bucket, 3) = 1 THEN 100.0     -- 与排名档位一一对应
      WHEN COALESCE(rk.rank_bucket, 3) = 2 THEN 80.0
      ELSE 60.0 END AS score_sales
自己开发 Codex + DataWorks MCP
骨架 手写 CTE、窗口、JOIN Agent 按 Skill 规范生成,拆 CTE、显式列、半开区间
时间窗口 每次都重新写,写法各异 复用同一个累计窗口 CTE
单位换算 靠记 写进规范,生成时就带上
复用 复制粘贴,越改越乱 读主题 README,按同一套模式新增

Agent 负责「不出低级的错」,人负责「不做错的判断」。 这句分工在这篇里最适合体现。

⑦ 对账验收:把「我觉得对」变成「有三张表能证明对」

sql 复制代码
-- 行数对账
SELECT COUNT(*) FROM ods_cs_complaint WHERE ds = '${bizdate}';
-- 金额对账(同单位)
SELECT SUM(amount) FROM src_table WHERE ... ;   -- 源端
SELECT SUM(amount) FROM ods_table WHERE ds = '${bizdate}';  -- 仓内
-- 主键唯一
SELECT COUNT(*) , COUNT(DISTINCT id) FROM ods_cs_complaint WHERE ds = '${bizdate}';
对账项 不合格的典型表现 大概率原因
行数 差几百行 增量条件或切分键有问题
金额 差整数倍 分 / 元换算错了
主键 出现重复 切分键选错或源端本身就一对多

自研也这么对账,区别是 Agent 会把这三条变成「每次必跑」的动作,而不是「想起来才跑」。


3. 批量:从 1 张到 100 张,边际成本趋近于零

单表跑通之后,输入不再是「再建一张表」,而是一份清单:

字段 示例
task_name ods_cs_complaint
source_datasource / source_table src_cs_db / t_complaint
target_table ods_cs_complaint
columns 显式列、顺序与 DDL 一致
split_pk id
file_folder_path 与同类任务同目录
cron_express / para_value 00 00 02 * * ? / bizdate=$bizdate

分五阶段推进,每一阶段都停下来能看、能查、能重跑:

阶段 动作 失败代价
A 批量生成 DDL / 同步脚本 / 计划 无(纯离线)
B 批量建目标表 低(IF NOT EXISTS
C 批量建任务 + 配调度 中(可改可删)
D 批量提交 + 发布 高(人工确认
E 验证:回读配置 + 补数据 + 抽检 ---

这是自研与 Agent 差距最大的地方:

表数量 自己开发 Codex + DataWorks MCP
1 张 约 3~4 小时 约 40~60 分钟
10 张 约 30~40 小时(且第 10 张和第 1 张一样累) 约 1~1.5 人天(含对账)
50 张 基本靠排期,人还会疲劳出错 清单驱动,并发跑批

图 3:表越多,差距越大。黄色区域是省下的工时------到 50 张,省下的不只是时间,还有疲劳带来的出错。

注意第三行那句括号:自研的痛不是慢,是「第 50 张的注意力和第 1 张不一样」,而疲劳正是事故的来源。


4. 与自研的差别:四条本质差异

图 4:同一件活的两条路径。左边是「人去操作界面」,右边是「人描述目标,Agent 去执行」。

把上面每一段的对照汇总,差异可以收成四条:

差异一:操作对象不同

自己开发 Codex + DataWorks MCP
操作的是界面:控件、向导、下拉框 操作的是接口 + 仓库:脚本、配置、SQL
结果只存在于平台上 结果同时在平台上和 Git 里

直白的后果: 自研建完任务,配置只存在于平台上,别人想学只能看你操作;Agent 建完任务,配置 JSON 和 SQL 都在仓库里,能 review、能复制、能改。

差异二:知识载体不同

自己开发 Codex + DataWorks MCP
规范在人脑 + 聊天记录 规范在 Skill / Reference
新人靠问、靠看老 SQL 猜 新人靠读文档 + 让 Agent 按规范生成
口径争论完就散了 结论回写文档,下一次自动生效

差异三:重复成本不同

自己开发 Codex + DataWorks MCP
第 N 张表与第 1 张一样费劲 第 N 张表的边际成本趋近于零
批量任务靠排期和加班 批量任务靠清单和脚本

差异四:质量来源不同

自己开发 Codex + DataWorks MCP
质量来自个人经验与自觉 质量来自规范被执行 + 固定验收动作
状态好时很稳,状态差时出事 每次执行都带上同样的检查

一句话总结这四条:自研是「一次性交付」,Codex + MCP 是「交付 + 沉淀」。

什么时候不该用

四条本质差异的另一面,是它的边界。下面这些场景,老老实实自己做:

场景 为什么
首次接入与权限铺垫 一次性投入:装 MCP、配 AK、开 RAM 权限,绕不过去
口径与业务判断 Agent 不该替业务做决定
破坏性动作(删表、改生产结构) 必须人工确认,不进自动化
极小的一次性改动 直接在控制台点两下更快,别为了用工具而用工具

把 Agent 用在「重复、有规范、可验证」的活上,把人的时间留给「判断、决策、担责」。


5. 价值体现在哪

5.1 交付节奏

环节 以前 现在
三张手工导表 每月人工导,导完对格式 每日自动入仓,分区可回溯
榜单产出 人工拼表,一个下午 调度自动产出,人只核对
新接一张源表 3~4 小时 40~60 分钟

5.2 质量与一致性

常见错误 以前 现在
分区没滤 / 硬编码日期 时有发生 规范里写死,Agent 默认带上
金额单位搞错(分 / 元) 靠人记 单位写进规范,转换显式可见
上下游依赖漏配 靠人记 建任务的固定步骤
发布后不验证 靠自觉 三张对账成为验收动作
口径改了没通知 靠聊天 改文档 + 血缘查影响面

5.3 知识资产(这块最容易被低估)

资产 自研之后 Codex + MCP 之后
建任务的配置 只在平台上 配置 JSON 在仓库里
加工逻辑 SQL 在平台上,改了没痕迹 SQL 在 Git,可 diff 可回滚
规范与口径 在人脑 在 Skill / Reference
排障路径 问人 血缘 + 文档
新人上手 口口相传 有明确阅读入口

5.4 一个可代入的账

项目 人工方式 Codex + DataWorks MCP 省下
单张源表:对字段到发布 3~4 小时 40~60 分钟 约 3 小时/表
4 张表一次性接完 2 人天 半天(含对账) 约 1.5 人天
每月重复导表 1~2 小时/月 0 约 2 人天/年
一次口径返工 半天起步 改一处文档 + SQL 防返工

但真正的价值不在省下的工时,而在三件事:

  1. 错误类型的改变------从「靠人记得」变成「流程兜住」
  2. 知识的可继承------链路不再跟着人走
  3. 可复核------每一步都留下痕迹,出问题能查到是哪一步

6. 六个坑

  1. 以为 MCP 什么都能干 → 老版单表同步不在工具面里,先 listTools 查清
  2. 让 Agent 直接对生产写 → 生成和建表可自动,发布要人工确认
  3. 只配了分区、忘了调度参数 → 两处都要写
  4. 发完就走 → 发布是异步的,不轮询等于没验
  5. 资源组填显示名 → 接口要的是资源组标识
  6. 依赖漏配 → 上游没到、下游照跑,产出「看着正常」的假数据

7. 结语

把这条链路和自研对照一遍,会发现差别其实只有一句:

自己开发,你在操作工具;用 Codex + MCP,你在描述目标,并且顺手把知识留了下来。

三句话收尾:

  1. 需求定完之后,第一件事是把口径翻译成建设清单,不是建表。
  2. Agent 负责不出低级的错,人负责不做错的判断,发布必须由人点头。
  3. 自研留下的是一个任务,Codex + MCP 留下的是一个任务加一套可复用的资产。

本文涉及的工具接口以阿里云 DataWorks MCP Server 与 DataWorks OpenAPI(2020-05-18)为例;示例中的项目空间、资源组、数据源、表名、指标与权重均已脱敏或替换为占位符。

系列建议:① 从 0 到 1(落地路径)→ ② 体系篇(长期记忆)→ ③ 血缘与高频表 → ④ 本篇(MCP 建仓链路 + 自研对比)→ ⑤ 用 MCP 做数仓治理。

=========================================================

人生得意须尽欢,莫使金樽空对月!

__一个热爱说唱的程序员。

今日份推荐音乐:弹壳Danko《Boss Life》

=========================================================

相关推荐
FII工业富联科技服务1 小时前
从台积电微通道散热看 AI 热管理:热量究竟如何从芯片走向机房?
人工智能·ai
峥嵘life1 小时前
2026华为AI码道 CodeArts 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言·python
AIGCmagic社区1 小时前
Show-Harness拆读,语义动作单元让VLM直接控机械臂,零样本跨任务89%
人工智能·aigc·具身智能·ai多模态
ZYJCSZKJ1 小时前
GEO 服务技术能力评估模型:交付体系、内容架构与持续运维的工程对比
人工智能
尘世中一位迷途小书童1 小时前
我为什么在 Windows 上做了一个翻译软件:SnapLingo
前端·人工智能·机器学习
Java后端的Ai之路1 小时前
大模型LLM评估完全指南
开发语言·人工智能·python·llm·评估
Kapaseker1 小时前
看完 AI 一天做出游戏,我只想问:你愿意掏钱吗?
人工智能
Xuantong_901 小时前
WAIC2026 深度观察:玄同科技 × 润建股份,共建中国东盟 AI 跨境 Token 产业生态,开启数字出海新范式
人工智能·ai·智能体
yxlalm1 小时前
零基础快速上手Trae创建Java项目
java·人工智能