3、数据模型设计:批次主数据模型、事件日志模型、关系图谱模型(DAG)
批次谱系查询的核心挑战在于:数据分散在多个异构系统(MES、WMS、QMS、ERP),且追溯链路需要支持双向(前向/后向)快速检索。为解决这一问题,我们设计了三个相互关联的数据模型层:批次主数据模型(静态属性)、事件日志模型(动态行为)、关系图谱模型(拓扑结构)。三者共同构成了跨系统追溯的“数据底座”。
3.1 批次主数据模型
批次主数据是追溯的“锚点”,记录每个批次从创建到完结的静态与半静态属性。该模型通常存储在关系型数据库(如 PostgreSQL、MySQL)或分布式 KV 存储(如 HBase)中,以批次 ID 作为全局唯一键。
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
| batch_id | VARCHAR(64) | 全局唯一批次编码(含工厂/产线前缀) | CN-SH-20250321-A001 |
| material_code | VARCHAR(32) | 物料编码 | MTR-8801-01 |
| batch_type | INT | 1=生产批次, 2=原料批次, 3=半成品批次, 4=成品批次 | 1 |
| quantity | DECIMAL(18,3) | 批次数量(单位由物料主数据定义) | 5000.000 |
| status | INT | 0=创建, 1=在制, 2=完成, 3=冻结, 4=报废 | 2 |
| produce_date | DATETIME | 生产日期 | 2025-03-21 08:00:00 |
| expire_date | DATETIME | 有效期(仅成品/原料批次) | 2025-09-21 23:59:59 |
| source_system | VARCHAR(16) | 数据来源系统标识 | MES |
| attributes | JSON | 扩展属性(如供应商批次号、生产线、班次) | {"line":"L03","shift":"A"} |
设计要点:批次主数据应尽量“轻量”,仅保留高频查询的静态字段。大量动态属性(如质检结果、工艺参数)建议通过事件日志模型关联,避免主表过宽导致写入性能下降。
3.2 事件日志模型
事件日志模型记录批次在其生命周期中发生的每一次“状态变更”或“业务动作”。它是追溯链路的“时序证据链”,也是后续构建关系图谱的原始数据源。该模型通常采用追加写的时序表或消息队列(如 Kafka)持久化。
-- 事件日志表核心结构(DDL 示例)
CREATE TABLE batch_event_log (
event_id BIGINT AUTO_INCREMENT PRIMARY KEY,
batch_id VARCHAR(64) NOT NULL,
event_type VARCHAR(32) NOT NULL COMMENT '事件类型:RECEIVE/CONSUME/SPLIT/MERGE/QC_PASS/QC_FAIL',
source_system VARCHAR(16) NOT NULL,
target_batch_id VARCHAR(64) DEFAULT NULL COMMENT '关联批次(拆分/合并时使用)',
operator VARCHAR(32) DEFAULT NULL,
event_time DATETIME(3) NOT NULL,
payload JSON DEFAULT NULL COMMENT '事件载荷(如数量、工单号、设备ID)',
INDEX idx_batch_time (batch_id, event_time),
INDEX idx_event_type (event_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
| 事件类型 | 触发场景 | 关键载荷字段 |
|---|---|---|
| RECEIVE | 原料入库、半成品接收 | 供应商批次、收货数量 |
| CONSUME | 投料消耗(批次被使用) | 消耗数量、工单号 |
| SPLIT | 批次拆分(如分装) | 子批次列表、拆分比例 |
| MERGE | 批次合并(如混批) | 源批次列表、合并后数量 |
| QC_PASS / QC_FAIL | 质检放行/不合格 | 检验单号、不合格代码 |
避坑提示:事件日志的
event_time 应使用业务时间(而非系统入库时间),避免因消息队列积压导致时序错乱。同时,建议对 target_batch_id 建立独立索引,以支持反向追溯(从子批次找父批次)。
3.3 关系图谱模型(DAG)
关系图谱模型将事件日志中的“批次间关联”抽象为有向无环图(DAG)。每个批次是一个节点,批次间的“消耗/产出”、“拆分/合并”关系构成有向边。该模型是快速追溯查询的核心——它避免了每次查询都扫描全量事件日志,而是通过预计算或物化路径实现毫秒级链路检索。
核心设计思路:将“事件”转化为“边”,将“批次”转化为“节点”,用图结构存储批次间的依赖关系。支持双向遍历:从原料查成品(前向),从成品查原料(后向)。
3.4 三种模型的协同关系
三个模型并非孤立存在,而是形成“主数据 → 事件日志 → 关系图谱”的逐层抽象与派生关系。下图展示了数据流转与查询路径:
3.5 模型选型与存储策略
| 模型 | 推荐存储 | 查询模式 | 数据量级 | 一致性要求 |
|---|---|---|---|---|
| 批次主数据 | 关系型数据库(MySQL/PostgreSQL)或 TiDB | 点查(by batch_id)、范围查(by date/status) | 百万~千万级 | 强一致(ACID) |
| 事件日志 | 时序数据库(InfluxDB/TimescaleDB)或 Kafka + 对象存储 | 按批次ID+时间范围扫描 | 亿级~百亿级 | 最终一致(允许少量乱序) |
| 关系图谱 | 图数据库(Neo4j/JanusGraph)或 关系型+物化路径 | 图遍历(BFS/DFS)、路径查询 | 千万~十亿级边 | 最终一致(异步构建) |
实践建议:对于中小规模场景(日增批次 < 10万),关系图谱可直接使用关系型数据库的“物化路径”方案(如存储每个批次的祖先路径字符串),避免引入图数据库带来的运维复杂度。大规模场景下,推荐使用 JanusGraph 或 Neo4j 以支持深度递归查询。