P2 Foundry
数据集与质量画像
把外部数据(数据源查询 / 文件上传 / 管道产物 / 对象快照)落成平台内“可寻址、可版本化、可追溯、可消费”的数据集资产;再用四因子画像(完整度 / 唯一度 / 有效性 / 新鲜度)给数据集持续“体检”,低于阈值自动进质量问题闭环。看完这 4 个故事,你就能自己把一张外部表变成有版本、有血缘、有健康分的平台数据资产。
数据工程师
业务分析师
数据集
质量画像
版本发布
血缘追溯
共 4 个故事
能 / 不能速览
✅ 这个主题能做
- 数据源查询(platform_ds)立即拉数建集,schema 自动推断,动态建行数据表落数
- CSV / JSON 上传建集(列名白名单防注入),预览前 50 行(钳 500)+ 基础画像(null 率 / distinct / top5 / avg)
- 版本发布与历史(指针推进,不拷贝行数据)、软删归档、血缘打点(数据源 / 上传 → 数据集)
- 四因子质量画像(completeness / uniqueness / validity / freshness)SQL 下推打分,总分 0~100
- 总分低于阈值自动产生质量问题,复用“确认 → 修复 → 重跑”闭环,评分历史可回看趋势
⛔ 这个主题做不了
- XLSX 上传本版显式拒绝(未引入 excelize,需另存 CSV),版本只进不退、无回滚端点
- 登记型数据集(管道产物 / 对象快照)只登记目录项,预览 / 画像返回空并诚实标注
- object scope 质量画像本版仅登记,运行明确报错;画像调度变更不实时生效(仅启动注册)
- validity 的 date 列 / PG 方言拉 ≤1000 行样本(sampled),是抽样估计而非精确值
- 数据集无对象级权限(任意登录用户可读写全部),行表无主键 / 索引
适用角色
本主题面向三个角色:
- 数据工程师:建数据集、做版本发布、配质量画像、修数据重跑——是核心使用者。
- 业务分析师:消费数据集与画像结论,收到低于阈值的问题提醒后参与确认。
- 运营人员:业务侧准备数据文件(CRM 导出 CSV 等)上传建集,不直接写 SQL。
平台管理员在审计里能看到谁建了数据集、谁发布了版本、谁运行了画像。
能力速览(能做什么)
数据集创建
platform_ds 经连接器执行查询立即拉数建集,或上传 CSV / JSON 解析落数;来源登记(source_type + source_ref)留档。
预览与基础画像
预览前 50 行(钳 500);基础画像逐列算 null 率 / distinct / top5,number 列附 avg,轻量预筛数据形态。
版本发布与历史
发布时把 schema + 行数快照入版本表、指针推进;版本历史倒序可回溯每个版本时点的口径。
血缘与软删
建集 / 上传成功自动打血缘边(数据源 / 上传 → 数据集);废弃数据集软删归档,可复查不物理删。
四因子质量画像
完整度 / 唯一度 / 有效性 / 新鲜度四因子 SQL 下推打分,加权总分 0~100,评分历史趋势可回看。
问题闭环
总分低于阈值自动落一条 profile_score 问题(复用数据质量页问题列表),确认 / 修复 / 重跑闭环。
调整指南(怎么调整)
- 改画像口径:权重(缺省 0.45 / 0.25 / 0.15 / 0.15)与阈值(0~100)可随时调;配 config.pk_column 才有唯一度、配 config.watermark_col 才有新鲜度,不配对应因子按 1(na)诚实标注。
- 改上传:表头先统一小写字母 / 数字 / 下划线再导出;XLSX 另存为 CSV 再传;空字段会落为 NULL 而非空串。
- 改版本:发布前先确认 row_count 已刷新(同步引擎写入后自动更新);changelog 写清当周口径便于审计回溯。
- 改调度:画像配 schedule(cron)后每天自动跑,但注意本版调度仅在启动时全量注册,运行中改 schedule 需重启才生效。
- 改来源:platform_ds 建集是同步执行的,大查询务必带 LIMIT;超大同步走同步引擎(B1-3)任务化。
做得好的场景
数据集把“外部数据 → 平台资产”这件事标准化,质量画像让健康度可量化、可跟踪,特别适合以下场景:
- 快速入平台:一键拉数或上传即建集,替代以前 DBA 写 DDL + 手工导数的数小时流程,且全程有记录。
- 口径留痕:每周发布版本 + changelog,“上周这张表多少行、什么口径”一查便知,不用翻聊天记录。
- 数据来路可追:数据源 / 上传 → 数据集的血缘边自动打点,配合下游消费(同步、画像、SQL 工作台)整条链路可查。
- 质量持续体检:四因子画像 SQL 下推量化,低于阈值自动告警进闭环,“坏数据”进不了下游而不靠人盯。
限制与不足
以下是明确的边界,使用前先知道:
- XLSX 上传降级:未引入 excelize 依赖,仅支持 CSV / JSON,XLSX 显式报错拒绝(P1 可补)。
- 版本不可回滚:current_version 指针只进不退,无“切回历史版本”端点(P2 扩展)。
- 行表无主键索引:ColumnDef.Nullable 统一 true、行表不设主键,去重靠同步引擎的幂等键。
- 登记型无行数据:pipeline_output / object_snapshot 仅登记目录项,预览 / 画像返回空(note 诚实标注)。
- object 画像未实现:可创建画像但运行明确报错;调度变更不实时增删条目。
- 无对象级权限:数据集与画像鉴权止于“登录即可访问”,权限收敛待后续版本。
场景故事
故事 1
老赵把订单查询落成数据集:拉数建集 + 预览 + 基础画像
场景:数据接入
角色:数据工程师
耗时:约 10 分钟
- 背景
- 老赵要把订单表落成平台内版本化数据集,供分析师消费、供同步引擎接管。他在“数据集”页新建,选演示数据源 foundry_demo_warehouse(ds_id=1),来源查询 SELECT * FROM orders LIMIT 1000,创建后立即预览前 5 行、看基础画像确认数据形态。
- 传统做法对比
- 以前拉一份订单快照要 DBA 写 DDL、手工导数、登记口径,快则 2~3 小时,还没有版本与血缘;现在一次 POST 立即拉数落表,schema 自动推断,预览与画像当场可见,每条记录都有来源登记。
- 角色
- 数据工程师(拥有数据源与数据集权限);下游由业务分析师与同步引擎消费。
- 操作步骤
-
- 登录平台(admin / admin1,端口 18081)
- 侧边栏“数据集”点“新建”
- 名称=orders_snapshot、数据源 ID=1、来源查询=SELECT * FROM orders LIMIT 1000
- 保存创建,打开详情抽屉“预览”看前 5 行
- 切“基础画像”Tab 重新计算,看每列 null 率 / distinct / top5
- 系统响应
- 创建返回示例:
POST /api/v1/datasets {"name":"orders_snapshot","source_type":"platform_ds","source_ref":{"ds_id":"1","query":"SELECT * FROM orders LIMIT 1000"}}
→ {"code":0,"data":{"id":"a1b2c3d4-...","rid":"e5f6...","uri":"dataset://foundry/e5f6...","name":"orders_snapshot","source_type":"platform_ds","row_count":5,"current_version":0,"status":"active","owner":"admin"}}
预览返回 5 行订单;基础画像返回每列 null 率 0、order_id distinct=5、amount avg=1294.1。
- 结果洞察
- 5 行订单全部落入 ds_dataset___foundry_<uuid> 行表(行表名由 URI 确定性推导,纯标识符可直接拼 SQL);基础画像显示各列无空值、amount 平均 1294.1,数据形态符合预期;血缘边 datasource:1 → dataset 已自动落库。数据集从此成为可寻址(dataset://foundry/<rid>)、可版本化、可追溯的平台资产。
- 调整建议
- 来源查询建议带 LIMIT(创建是同步执行,大查询会占住请求);外部列名不合规会 422,先归一好再查;想被同步引擎接管,把数据集设为同步目标即可;行表无索引,大表画像聚合(COUNT DISTINCT)会较慢。
- 动手试一试
- 登录:admin / admin1。页面路径:数据集 → 新建。输入内容:名称 orders_snapshot、数据源 ID=1、查询 SELECT * FROM orders LIMIT 1000。预期结果:创建返回 row_count=5,预览显示 5 行,基础画像各列 null 率 0。
- 限制提示
- platform_ds 建集同步执行,超大来源查询会占住请求连接;行表无主键 / 索引,仅用于预览与画像;demo 数据源每次启动重建,但已落平台库的数据集行数据不受源表重建影响。
故事 2
小周传客户名单:XLSX 明确拒绝、坏表头 422,改对后秒建集
场景:文件上传
角色:运营人员
耗时:约 5 分钟
- 背景
- 运营小周手头有一份 CRM 导出的客户名单 customers.xlsx,想传成数据集供销售自助查。平台上传只接受 .csv / .json,她先按提示另存为 CSV,但表头是 Excel 默认的大写风格“Order ID”,第一次上传被拒,报错精确到具体列名。
- 传统做法对比
- 以前表格数据进平台要么让 DBA 手动建表导入(排期半天),要么丢给分析师自行处理(来源无从追溯);现在上传建集分钟级完成,原始文件落盘留档、血缘可查,坏表头当场 422 说清原因,不用猜。
- 角色
- 运营人员(业务侧准备数据文件);数据工程师协助规整列名。
- 操作步骤
-
- 把 customers.xlsx 另存为 customers.csv
- 打开“数据集”页“上传”,选文件(accept 仅 .csv / .json)
- 先上传列名含大写 / 中文的版本,观察报错
- 把表头改为小写合法列名(^[a-z][a-z0-9_]*$)再传
- 上传成功后打开详情查看 schema 与预览
- 系统响应
- 上传返回示例:
POST /api/v1/datasets/upload
XLSX → {"code":"INVALID_REQUEST","error":"XLSX 暂不支持:本版未引入 excelize 依赖,已降级为仅支持 CSV/JSON,请将文件另存为 CSV 后上传"}
坏表头 → {"code":"VALIDATION_ERROR","error":"列名 \"Order ID\" 非法:须匹配 ^[a-z][a-z0-9_]*$(小写字母/数字/下划线)"}
改对后 → {"code":0,"data":{"name":"customers","source_type":"upload","source_ref":"{\"filename\":\"customers.csv\"}","row_count":4,"current_version":0}}
- 结果洞察
- 上传不是黑盒:XLSX 明确告知“另存为 CSV”,坏列名精确到具体名字并给出正则——这是防注入的底线,不是 bug。改好后 4 行客户落库,原始文件存在 data/foundry/datasets/<uri>/ 下可溯源,血缘边 upload → dataset 已打点。空字段按 NULL 落库,JSON 上传列序按键名字典序确定。
- 调整建议
- 表头统一小写字母 / 数字 / 下划线再导出;空字段会上传为 NULL(不算空串);想固定列序用 CSV(JSON 对象无序,列序按字典序);涉及敏感数据注意上传范围,原始文件会长期留档。
- 动手试一试
- 登录:admin / admin1。页面路径:数据集 → 上传。输入内容:任意含中文 / 大写表头的 CSV(如 客户ID,姓名)。预期结果:422 报列名非法;改成 customer_id,name 后重传,row_count 正确、详情可预览。
- 限制提示
- 单文件上限 32MB;XLSX / .xls 明确不支持需另存 CSV;表头重复列名 422;空文件 / 空 JSON 数组 400;CSV 类型推断全数值→number、全布尔→bool、否则 text,混类型列统一降级 text 不报错。
故事 3
周快照版本发布:v1/v2 历史可回溯,指针推进不复制数据
场景:版本治理
角色:数据工程师
耗时:约 5 分钟
- 背景
- orders_snapshot 每周五发布一次版本,作为口径快照供审计与回溯。老赵连续两周发布 v1、v2,并在 changelog 里写明当周口径;之后想确认“v1 时行数是多少、schema 长什么样”,打开版本历史一看便知。
- 传统做法对比
- 以前表结构一变旧数据就说不清——“这表上周多少行?口径是什么?”全靠聊天记录和记忆;现在每次发布把 schema + 行数快照进版本表,版本历史倒序一目了然,指针式发布不复制数据。
- 角色
- 数据工程师(发布版本);审计与下游消费方(查版本历史)。
- 操作步骤
-
- 打开数据集详情抽屉“版本历史”Tab
- 点“发布版本”,changelog 填 “2026-08-30 周快照”
- 返回看 current_version 变为 1(再发布则 2、3…)
- 第二次发布前先往数据集追加行数据,再发布 v2
- 查看版本历史,对比 v1 / v2 的 row_count
- 系统响应
- 发布与历史返回示例:
POST /api/v1/datasets/a1b2c3d4-.../versions/publish {"changelog":"2026-08-30 周快照"}
→ {"code":0,"data":{"version":1}}
GET /api/v1/datasets/a1b2c3d4-.../versions
→ {"code":0,"data":{"versions":[
{"version":2,"row_count":8,"changelog":"2026-08-30 周快照","created_by":"admin"},
{"version":1,"row_count":5,"changelog":"2026-08-23 周快照","created_by":"admin"}]}}
- 结果洞察
- 版本发布只推指针(current_version++),不拷贝行数据,空间开销 O(1);历史版本可回溯“当时 schema + 行数”,配合血缘整条来路可查。并发发布由唯一索引 + 哨兵重试兜底(最多 3 次,仍冲突返回 409),不会出现重复版本号。
- 调整建议
- changelog 写清楚当周口径(含哪些过滤 / 字段),审计时一眼看懂;发布前先确认 row_count 已刷新(同步引擎写入后自动更新);归档数据集不可发布版本(400);想记录“删除”用软删,物理清理属后续运维能力。
- 动手试一试
- 登录:admin / admin1。页面路径:数据集 → orders_snapshot → 版本历史。输入内容:changelog “2026-08-30 周快照” 点发布。预期结果:返回 version=1,版本历史出现 v1(row_count=5);再发布一次变 v2。
- 限制提示
- 版本只进不退,没有“切回历史版本”的端点(回滚属 P2 扩展);版本号每数据集内从 1 自增;详情 GET 的 schema 是“当前” schema,历史 schema 在版本记录里;版本记录随数据集软删保留。
故事 4
四因子画像体检:总分 76.69 低于阈值,自动进问题闭环
场景:质量体检
角色:数据工程师
耗时:约 8 分钟
- 背景
- 平台要求所有“上线口径”的数据集每周体检一次。老赵为 regional_sales 数据集建了一份四因子画像:阈值 80、默认权重,config 配 pk_column=store_code、watermark_col=report_date,然后立即运行看总分。这份数据传上去就一直没人管,他心里没底。
- 传统做法对比
- 以前判断“表干不干净”靠抽查几条数据 + 人眼判断,漏掉就漏掉;现在四因子 SQL 下推量化成总分,完整度 / 唯一度 / 有效性 / 新鲜度四项一眼看清,低于阈值自动进问题闭环,不用人盯。
- 角色
- 数据工程师(建画像、跑分、修数据);业务分析师收到问题提醒后参与确认。
- 操作步骤
-
- “数据质量”页切到“质量画像”Tab,新建画像
- 名称=regional_sales_quality、scope_type=dataset、scope_id=regional_sales 数据集 id、阈值=80
- config 填 pk_column=store_code、watermark_col=report_date
- 点“运行”,看返回的总分与因子明细
- 总分 76.69 < 80 → 到“问题”Tab 看自动产生的 issue,确认并修复数据后重跑
- 系统响应
- 运行返回示例:
POST /api/v1/quality/profiles/3f0c.../run
→ {"code":0,"data":{"score":{"id":"...","target_type":"dataset","completeness":0.9375,"uniqueness":0.9,"validity":0.8,"freshness":0,"total":76.69},"details":{"table_name":"ds_dataset___foundry_","row_count":20,"issue_created":true,"factors":[
{"factor":"completeness","value":0.9375,"method":"pushdown","detail":"空值 5/80 单元(4 列 × 20 行)"},
{"factor":"uniqueness","value":0.9,"method":"pushdown","detail":"DISTINCT store_code = 18 / 20 行"},
{"factor":"validity","value":0.8,"method":"pushdown","detail":"typeof 下推:非法 3 / 非空 15"},
{"factor":"freshness","value":0,"method":"pushdown","detail":"MAX(report_date)=2026-07-01,距今 1440.0h(线性衰减窗口 720h)"}]}}}
- 结果洞察
- 四因子全部 SQL 下推:completeness 0.9375(有 5 个空单元)、uniqueness 0.9(18 个不重复门店,有重复)、validity 0.8(sales_amount 有 3 个 “N/A” 非法值)、freshness 0(report_date 距今 60 天,超出 720h 线性衰减窗口)——分数低不是猜的,每项都有 detail 可查。低于阈值自动在 data_quality_issues 落一条 RuleType=profile_score、Severity=warning 的问题,走“确认 → 修复 → 重跑”闭环;连续低于阈值不会重复刷问题,恢复后再跌破会重新触发。
- 调整建议
- 阈值别拍脑袋:口径越重要阈值越高;没配 pk / watermark 时对应因子按 1(na)诚实标注,想测唯一度 / 新鲜度就补 config;validity 的 date 列与 PG 方言走样本路径(sampled),要精确值注意行数规模;修复数据后重跑,分数回升到阈值上即不再产生新 issue。
- 动手试一试
- 登录:admin / admin1。页面路径:数据质量 → 质量画像 → 新建。输入内容:scope_type=dataset、scope_id=刚建的数据集、阈值 80、config 填 pk_column / watermark_col。预期结果:run 返回 total 与四因子明细;低于阈值时问题列表出现 profile_score 记录。
- 限制提示
- object scope 画像本版仅登记,运行明确报错;画像 schedule 变更不实时增删调度条目(仅启动时注册,改动需重启);画像无对象级权限,登录即可看任意 scope 的评分;当前画像只算本地行表,直查源表新鲜度属后续版本。
常见问题
数据集和物理表有什么区别?
数据集是“平台内版本化数据资产”:主记录(fd_datasets)+ 版本快照(fd_dataset_versions)+ 物理行表(ds_<rid安全名>)+ 血缘 / URI 寻址。行表只是存储,数据集还承载来源登记、schema、统计、版本、owner、状态。
版本能回滚吗?
本版只进不退:发布版本推 current_version 指针,不拷贝数据,版本历史可回溯每个版本时点的 schema 与行数;“切回历史版本”的端点属 P2 扩展,暂未实现。
为什么 CSV 表头会被拒绝?
物理列名白名单 ^[a-z][a-z0-9_]*$(小写字母 / 数字 / 下划线)是防注入底线,非法列名一律 422 并给出具体列名,不做静默改写。中文只能放在数据集 name / description 展示层,上传表头含中文请先改名。
质量画像和人工质量规则有什么区别?
规则是“检查点”(该列不许有 NULL、须符合格式),画像则是“仪表盘”(四因子加权总分 + 趋势)。两者互补:规则检查的明细违规可被画像的总分趋势兜底,画像降分又能触发到规则层查明细;低于阈值的画像会落一条 profile_score 问题共用同一张问题表。
为什么 freshness(新鲜度)因子是 0?
新鲜度按水位列最大值距今线性衰减:age ≤ 0h → 1,age ≥ 720h(30 天)→ 0。regional_sales 的 report_date 距今 60 天,已超出衰减窗口所以是 0;没配 watermark_col 时该因子按 1(na)记录并标注。
XLSX 为什么不支持?
本版未引入 excelize 依赖,仅支持 CSV / JSON,XLSX 上传会显式报错并提示“另存为 CSV 后上传”——诚实降级而非静默出错。XLSX 解析属 P1 扩展点。
主题小结
一句话:数据集把“外部数据 → 平台资产”标准化(创建 / 预览 / 版本 / 血缘 / 归档),质量画像用四因子 SQL 下推持续量化健康度并自动告警闭环。记住几个边界:XLSX 上传拒绝、版本只进不退、登记型无行数据、object 画像未实现、无对象级权限。