在离散制造与电子装配产线上,一个产品从投料到出货会经历工单排产、批次归集、单件序列号绑定三道工序。MES 与追溯平台要回答的核心问题是:这个 SN 属于哪个批次、这个批次挂在哪个工单、这个工单又产出了哪些 SN。工单-批次-SN 构成一条三级关系链,数据模型设计得对不对,直接决定正向追溯和反向反查能不能在一次接口调用里返回完整链路。
工单-批次-SN 三级关系的数据模型,应该以"工单是生产计划单元、批次是质量与归集单元、SN 是单件身份单元"三层定位为基础,通过两张中间关系表把三层捏合,并在接口层提供按 SN 反查工单、按工单正查 SN 以及按批次聚合统计三条反查链路。车间场景下,正向追溯走主键链路,反查靠预建的反向索引表,这样既保证追溯查询稳定在毫秒级,又不会把三级关联做成一张无限膨胀的宽表。
一、三层的业务定位与建模约束
工单是生产计划单元。它来自 ERP 或 APS 下达的制造订单,携带产品编码、BOM 版本、计划数量、计划起止时间与排产状态。一张工单可以对应一个或多个批次,取决于车间是按自然批次归集还是按工序段切分。
批次是质量与归集单元。同批次内的物料或半成品共享一组过程属性:来料批次、投料时间、关键工艺参数区间、检验结论。批次是质量追溯的最小可召回集合,发生客诉或抽检不合格时,按批次锁定范围比按工单更精确。
SN 是单件身份单元。序列号在最终装配或关键工序被赋予,与一台设备或一件成品一一对应。SN 的绑定时刻就是追溯链路的起点,所有后续的反查都要能从 SN 一路回到批次与工单。
建模约束有三条。第一,三层不互相嵌套:工单表不存 SN 清单,SN 表不存工单号,关联通过中间关系表完成。第二,批次到工单是多对一,SN 到批次在正常流程里是多对一,但在返工、拆箱重绑等异常场景下需要允许 SN 历史上出现多条绑定记录,因此 SN-批次关系表必须保留绑定时间与状态。第三,任何一级的"反查"都不应依赖运行时动态多表 JOIN,而是由关系表上的索引与预写链路在写侧一次性准备完成。
二、核心表与两张关系表
三张主表各自收敛本层属性。
工单表 production_workorder 记录工单维度信息:workorder_no 工单编号作为业务主键;product_code 与 bom_version 锁定产品与 BOM 版本;planned_qty 计划数量、completed_qty 完工数量;status 状态覆盖未开始、生产中、暂停、完工、关闭;plan_start_time 与 plan_end_time 定义排产窗口;site_id、workshop_id、line_id 定位到工厂车间产线。工单表不携带任何批次或 SN 字段。
批次表 production_lot 记录批次维度:lot_no 批次号;source_workorder_no 通过外键或业务键指向所属工单;material_code 与 incoming_lot_no 记录来料信息与上游供应商批次;process_window_start 与 process_window_end 是批次覆盖的工艺时间窗;quality_result 记录批次级检验结论,典型值为合格、不合格、让步接收、待检;yield_qty 与 scrap_qty 统计批次良率与报废数。
序列号表 asset_serial_number 记录 SN 维度:serial_number 序列号值;sn_type 类型区分整机 SN、关键部件 SN、板级 SN;product_code 与 sn_status 状态覆盖未绑定、已绑定、已出库、已退货、已报废;bind_time 记录首次绑定时间;first_operator_id 与 bind_station_id 记录绑定工位上下文。SN 表同样不直接指向批次与工单。
两张关系表负责捏合。工单-批次关系表 workorder_lot_rel 是批次归集到工单的纽带:主键为 lot_no 加 workorder_no 加 rel_type,rel_type 区分正常归属与跨工单转入转出;assign_time 与 assign_operator_id 记录归属建立时刻;rel_status 覆盖生效、撤销、合并。一个 lot_no 同时出现多行时,只有 rel_status=生效 的行参与当前追溯。
序列号-批次关系表 sn_lot_rel 是 SN 绑定批次的纽带:主键为 serial_number 加 lot_no 加 bind_time;bind_type 区分正常绑定、返工重绑、拆箱重归、检验回退;bind_status 覆盖生效、解绑、作废。同一条 SN 在多轮返工中可以累积多条记录,反查时以 bind_status=生效 且 bind_time 最大的行作为当前归属。
这种"三主表 + 两关系表"的结构,比在工单表里塞一个 SN JSON 数组或把 SN 表加 workorder_no 宽列更稳定:关系变化发生在关系表,主表只记录本层属性,反查靠关系表索引完成。
三、反查链路设计的索引与物化选择
追溯系统最常见的查询是"给我一个 SN,我要看到它所属批次与工单的所有关键属性"。这条从 SN 到工单的反查链路,如果在接口层做成两跳 JOIN,延迟会随着批次规模线性放大。工程上通常有三种做法,按代价从低到高排列。
做法一是关系表索引覆盖。在 sn_lot_rel 上建 serial_number 加 bind_status 加 bind_time 的联合索引,查当前有效归属只需一次索引扫描拿到 lot_no;再在 workorder_lot_rel 上建 lot_no 加 rel_status 联合索引,第二跳拿到 workorder_no。两跳都是等值查找,延迟稳定。约束是 SN 反查接口必须接受"当前归属"和"历史归属"两种模式:当前归属取 bind_time 最大的生效行;历史归属返回该 SN 全部绑定记录的时间线。
做法二是工单-SN 物化链路表。在写入侧,每当 sn_lot_rel 新绑定且 workorder_lot_rel 归属确定时,异步写一条 trace_sn_workorder 记录:serial_number、workorder_no、lot_no、trace_status、trace_time。这张表以 serial_number 为主键或唯一索引,反查变成单表查询,延迟最低。代价是写入侧多了一次衍生写,并且当批次跨工单转入转出时,需要把旧 trace 记录标记失效并写入新 trace,保证 trace_status 生命周期与关系表一致。适合 SN 反查 QPS 高、对延迟敏感的追溯平台。
做法三是只建 SN 到工单的"快捷外键"。在 sn_lot_rel 写入时直接把当前 workorder_no 落到关系行上。好处是接口简单,坏处是工单-批次关系变更时必须扫描全部受影响 SN 的关系行去做级联更新,写放大不可控。在批次经常合并拆分、SN 量级在百万以上的车间里,这种做法会在批次调整当天拖垮数据库。
综合建议:核心追溯接口选用做法二的物化链路表,关系表索引作为校验与对账的兜底;做法三仅在小规模、批次几乎不变更的产线试点。
四、反查接口的路径与入参出参
围绕三级关系,接口层需要暴露三条查询路径。每条路径的入参、出参和版本约定明确后,MES、WMS 与追溯平台对接时才能直接拼装画面。
路径一:按 SN 反查工单与批次。推荐 REST 路径 GET /api/v1/trace/sn/{serial_number},可选查询参数 include_history 控制是否返回历史绑定。正常响应返回当前归属:包含 serial_number、sn_status、当前 lot_no 与批次关键字段(quality_result、process_window)、当前 workorder_no 与工单关键字段(product_code、bom_version、status、plan_start_time),以及 bind_time 和 trace_time。当 include_history=true 时,在 responses 数组内追加该 SN 的历史绑定时间线,每条记录包含 lot_no、workorder_no、bind_type、bind_status、bind_time。若 SN 未绑定,返回 404 并附带 result_code=SN_NOT_BOUND。批量场景提供 GET /api/v1/trace/sn/batch,入参为 serial_number 列表,出参为列表加总数,并返回部分失败的 partial_failure 明细。
路径二:按工单正查 SN 列表。REST 路径 GET /api/v1/trace/workorder/{workorder_no}/serials,查询参数支持 page、page_size、sn_status 过滤、以及 expand_lot 控制是否同时展开批次信息。出参返回该工单当前有效产出 SN 的分页列表。这条路径在工单完工盘点、出货复核场景高频使用,因此需要在写入侧通过物化链路表 trace_sn_workorder 的 workorder_no 索引支撑,避免运行时从批次再扩散到 SN。
路径三:按批次聚合统计。REST 路径 GET /api/v1/trace/lot/{lot_no}/summary,返回该批次的工单归属、绑定 SN 总数、按 sn_status 拆分的状态计数、按 bind_type 拆分的绑定类型计数,以及质量结论与工艺时间窗。出参不返回 SN 清单本身,只提供汇总与状态分布;如需 SN 清单,调用方应走路径四的 SN 列表。这条路径为批次级召回与不合格品锁定提供数据,适合在质量系统侧直接消费。
可选路径四:按批次列举 SN。REST 路径 GET /api/v1/trace/lot/{lot_no}/serials,配合 sn_status 与 page/page_size 使用,返回该批次当前有效绑定的 SN 分页列表。与路径三的关系是"统计 vs 明细",同一 lot_no 下两条路径共享写入源,避免统计与明细出现不一致。
五、写入侧的生命周期与一致性
三级关系的稳定性,一半取决于写入侧怎么维护生命周期。绑定、解绑、批次归属变更、SN 状态流转,每一步都会在关系表与物化链路表上留下记录,接口反查读到的就是写入侧写出的样子。
SN 绑定的写入流程。工位 PDA 或读码器上报 SN 绑定后,服务侧先校验 SN 当前 sn_status 允许绑定,再写入 sn_lot_rel 新增一行 bind_status=生效。如果选用了物化链路表,且该 lot_no 的 workorder_lot_rel 归属已经确定,同步写一条 trace_sn_workorder;若归属尚未确定,trace 记录暂缓,归属确定后由归属变更事件补齐。绑定写入需要保证 sn_lot_rel 与 trace 记录在同一事务或同一消息事务内,避免 SN 已绑定但物化链路未写的"半绑定"状态。
SN 解绑与重绑。返工或检验回退时,原 sn_lot_rel 行的 bind_status 翻转为解绑或作废,bind_type 记录回退原因;新绑定写入新行。物化链路表侧对应地把旧 trace 标记 trace_status=失效,并写新 trace。解绑操作必须幂等:重复解绑请求不应产生多条解绑记录,接口用 SN 加操作流水号做幂等键,与条码扫描事件表的幂等做法同源。
批次归属变更的级联。当 lot_no 从工单 A 转入工单 B 时,workorder_lot_rel 写入新归属行并将旧行 rel_status 置为撤销。此时需要把该批次下全部 trace_status=生效 的 trace 记录扫描出来,翻转为失效并写入新工单的 trace。这一步是写入最重的场景,工程上通常做成异步任务:接口先返回归属变更已受理,后台任务在分钟级内完成 SN 物化链路翻转,期间反查接口对受影响的 SN 返回 trace_status=变更中 并附带新旧两个工单号,避免调用方读到不一致的归属。
六、跨系统对接时的边界与版本约定
工单-批次-SN 模型通常同时被 MES、WMS、质量系统与追溯平台消费。对接时如果不约定边界,同一个 lot_no 或 SN 在不同系统里的归属就会出现分歧。
职责边界。工单表与生产状态由 MES 或制造执行侧维护;批次表与质量结论由质量系统或实验室 LIMS 在检验完成后回写;SN 表由追溯平台或序列号服务统一分配,防止不同产线或供应商产生 SN 冲突。关系表由谁写,取决于绑定发生的物理位置:工位绑定由产线终端经追溯网关写入 sn_lot_rel;批次归属由 MES 在排产与完工确认时写入 workorder_lot_rel。谁写谁负责幂等与事务。
接口版本与字段收缩。外部调用方不应依赖主表全量字段。反查接口出参只暴露追溯必要字段,随版本演进做字段收缩而不是膨胀。新增业务字段(如追溯要加"供应商工单号")应先在批次或工单主表侧扩展,再由反查接口在版本更新时显式纳入出参,而不是让每个调用方各自拼接。
数据冻结与历史反查。工单完工并关闭后,该工单产出的 SN 归属进入冻结期:sn_lot_rel 仍允许返工重绑产生新行,但不允许再往该工单追加新的生效归属。历史反查接口需要明确冻结期的返回策略——冻结后新发生的 SN 状态变化仍然返回,但归属链路的 workorder_no 锁定在冻结快照。这对审计与客诉回复的一致性很关键。
七、FAQ
问:SN 能不能直接在建表时加 workorder_no 列,省掉关系表?
答:不建议。SN 的归属在返工、跨工单转入转出时可能变更,直接加 workorder_no 等于把可变关联写死在主表,级联更新会把 SN 表拖慢。关系表把"当前归属"与"历史归属"同时容纳,是更稳的结构。
问:一个批次能不能挂在多个工单?
答:在正常排产下批次到工单是多对一。出现跨工单转入转出时,workorder_lot_rel 会有多行,但同一时刻只有 rel_status=生效 的行参与追溯。接口反查返回的是当前生效归属,历史行通过 include_history 类参数暴露。
问:物化链路表 trace_sn_workorder 和关系表不一致怎么办?
答:写入侧需要保证绑定与 trace 写入在同一事务或消息事务内;归属变更的级联翻转是异步的,翻转期间反查接口返回 trace_status=变更中 并附带新旧工单号。日级别跑一次 trace 与关系表的对账任务,差异落入对账报表并由后台任务修复,避免差异累积。
问:SN 反查接口要不要支持按前缀模糊查?
答:不建议。serial_number 是等值身份标识,模糊查询会把索引扫描放大到全表。调用方有"大概范围"诉求时,应通过工单或批次维度缩小范围后再按 SN 等值反查,而不是在 SN 上做 like 查询。
问:批次汇总接口要不要同时返回 SN 清单?
答:不返回。批次汇总只承担统计职责(总数、状态分布、质量结论),SN 明细由按批次列举 SN 的专用接口承担。两者同源但职责分离,避免汇总接口在大批次场景下把内存和网络撑满。
八、小结
工单-批次-SN 三级关系的数据模型,核心取舍在于"关联发生在哪里"和"反查从哪一跳开始"。工单是计划单元、批次是归集单元、SN 是单件身份单元,三层各守其表,用 workorder_lot_rel 与 sn_lot_rel 两张关系表把链路易于维护地捏合。反查接口以 SN 反查工单为第一条路径,工单正查 SN 为第二条路径,批次聚合统计为第三条路径,写入侧通过物化链路表把 SN 到工单的反向查询压到单表等值查找。
这套结构在条码追溯、SMT 过站与离散装配车间里都能复用:关系变化收在关系表,主表不收宽列,反查不靠运行时多表 JOIN。对接方拿到的是稳定版本的路径与出参,而不是不断膨胀的全量快照。下一步可以把绑定接口、归属变更接口与物化链路对账任务的时序图整理成对接 Checklist,和 MES、质量系统与追溯平台的对接方一起评审。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。