3. 测试数据模型设计

在测试结果追溯系统中,数据模型决定了“能不能追溯、追溯得多快、追溯得多准”。很多项目一开始只建一张大表,把产品条码、工位、测试项、测量值、上下限、结论全部塞在一起,短期看似省事,一旦要按序列回放、按步骤统计不良、按版本对比限值,就会陷入重复数据、更新异常和查询缓慢的困境。本节围绕五个核心实体——测试项目、测试序列、测试步骤、测量结果、判定结论——讨论实体关系、主键与外键设计,以及规范化与反规范化的取舍。

一、五个核心实体的职责边界

先把每个实体“管什么”界定清楚,是建模的第一步。

  • 测试项目(TestItem):描述“测什么”,是限值与判定规则的载体。典型字段包括项目编号、项目名称、单位、量程、下限、上限、判定方式(上下限、单边、枚举、文本匹配)、适用产品型号、版本号。它是相对静态的字典数据。
  • 测试序列(TestSequence):描述“按什么顺序测”,是测试项目的有序集合,对应一个产品型号或工艺路线。典型字段包括序列编号、序列名称、适用型号、版本、生效日期。
  • 测试步骤(TestStep):序列与项目之间的“连接实体”,描述“第几步测哪个项目、用什么条件测”。典型字段包括步骤序号、所属序列、引用项目、采集通道、激励条件、延时、重试次数。它把“顺序”和“项目”解耦。
  • 测量结果(Measurement):描述“实际测到了什么”,是每次执行产生的事实数据。典型字段包括结果ID、产品条码、序列、步骤、测量值、单位、采集时间、设备编号、操作员。
  • 判定结论(Verdict):描述“这一步/这一台是否合格”,以及依据。典型字段包括结论ID、关联测量结果、判定结果(Pass/Fail/Retest)、判定依据(引用的限值快照)、判定时间。

关键点在于:测量结果与判定结论应分开存储。测量值是客观事实,判定结论是依据规则产生的主观判断。若把两者混在一列,一旦限值调整或判定规则升级,历史数据的“当时判定”就无法还原,追溯会失真。

二、实体关系与主外键设计

五个实体构成一条清晰的引用链:测试序列 1—N 测试步骤,测试项目 1—N 测试步骤,测试步骤 1—N 测量结果,测量结果 1—1 判定结论。下面用一张关系图呈现主键、外键与基数。

测试数据模型:实体关系与主外键 测试项目 TestItem PK 项目编号 ItemID 项目名称 / 单位 下限 LSL / 上限 USL 判定方式 / 版本号 适用型号(外键→型号) 测试序列 TestSequence PK 序列编号 SeqID 序列名称 / 适用型号 版本 / 生效日期 状态(启用/停用) 测试步骤 TestStep PK 步骤ID StepID FK 序列编号 SeqID FK 项目编号 ItemID 步骤序号 / 采集通道 激励条件 / 延时 / 重试 测量结果 Measurement PK 结果ID MeasID FK 步骤ID StepID 产品条码 / 测量值 单位 / 采集时间 设备编号 / 操作员 判定结论 Verdict PK 结论ID VerdictID FK 结果ID MeasID 判定结果 Pass/Fail 限值快照 LSL/USL 判定时间 / 规则版本 1 : N N : 1 1 : N 1 : 1 引用链:序列 → 步骤 → 测量结果 → 判定结论;项目通过步骤被引用 紫色字段为外键,是追溯查询的连接键

主键选择上,建议使用无业务含义的代理键(自增整数或GUID)作为物理主键,同时为业务编号建立唯一约束。原因是项目编号、序列编号可能随版本调整,若直接用作主键,历史数据的外键会随之漂移。外键方面,测量结果必须携带步骤ID,而步骤ID又指向序列与项目,因此“条码→序列→步骤→项目→限值”的完整追溯路径可以通过三次连接完成。

三、规范化:先做对,再谈快

按第三范式设计,上述五张表基本消除了传递依赖:项目限值只存一份,序列顺序只存一份,测量事实只存一份。这样带来的直接好处是:修改某项目上限,只需改一行;新增一个步骤,不影响历史测量;统计某型号某项目的不良率,只需按外键聚合。

但纯规范化在测试场景会遇到两个现实问题。第一,测量结果表数据量极大,一次产线测试可能每秒写入数十条,若每次判定都要回连项目表取限值,高频写入下连接开销明显。第二,历史追溯要求“还原当时判定”,而项目表的限值会随版本更新,若判定结论只存外键,回看旧数据时取到的是新限值,结论就错了。

四、反规范化:把“当时快照”固化下来

针对上述问题,常用的反规范化手段是在测量结果或判定结论中冗余关键字段。典型做法是在判定结论中冗余 LSL、USL、判定方式、规则版本号,形成“限值快照”。这样即使项目表后续修改,历史判定仍可原样复现。另一个做法是在测量结果中冗余项目编号与序列编号,减少追溯查询的连接次数。

反规范化的代价是写入时需保证冗余字段与主表一致。工程上通常用两种方式控制:一是由写入程序在插入时统一填充快照字段,二是对字典表采用“只增不改”的版本化策略——修改限值不覆盖旧行,而是新增一条带新版本号的项目记录,旧测量仍指向旧版本。后者更彻底,但要求所有查询都带版本条件。

经验取舍:字典类实体(项目、序列、步骤)保持规范化,测量与判定这类事实表适度反规范化。事实表冗余的是“判定所需的限值快照”,而不是把项目名称、单位等展示字段全部复制,避免冗余失控。

五、一个可落地的建表示例

下面给出核心表的简化DDL,体现主键、外键与快照字段的设计意图(以通用SQL语法示意,具体类型可按数据库调整)。

CREATE TABLE TestItem (
  ItemID      INTEGER PRIMARY KEY,
  ItemCode    VARCHAR(32) UNIQUE NOT NULL,
  ItemName    VARCHAR(64) NOT NULL,
  Unit        VARCHAR(16),
  LSL         DECIMAL(12,4),
  USL         DECIMAL(12,4),
  JudgeMode   VARCHAR(16),      -- Limit/OneSide/Enum/Text
  Version     INTEGER NOT NULL
);

CREATE TABLE TestSequence (
  SeqID       INTEGER PRIMARY KEY,
  SeqCode     VARCHAR(32) UNIQUE NOT NULL,
  SeqName     VARCHAR(64),
  ModelCode   VARCHAR(32),
  Version     INTEGER NOT NULL,
  ActiveFlag  SMALLINT DEFAULT 1
);

CREATE TABLE TestStep (
  StepID      INTEGER PRIMARY KEY,
  SeqID       INTEGER NOT NULL REFERENCES TestSequence(SeqID),
  ItemID      INTEGER NOT NULL REFERENCES TestItem(ItemID),
  StepNo      INTEGER NOT NULL,
  Channel     VARCHAR(16),
  DelayMs     INTEGER,
  RetryTimes  INTEGER DEFAULT 0
);

CREATE TABLE Measurement (
  MeasID      BIGINT PRIMARY KEY,
  StepID      INTEGER NOT NULL REFERENCES TestStep(StepID),
  Barcode     VARCHAR(64) NOT NULL,
  MeasValue   DECIMAL(14,5),
  Unit        VARCHAR(16),
  MeasTime    TIMESTAMP NOT NULL,
  DeviceID    VARCHAR(32),
  Operator    VARCHAR(32)
);

CREATE TABLE Verdict (
  VerdictID   BIGINT PRIMARY KEY,
  MeasID      BIGINT NOT NULL REFERENCES Measurement(MeasID),
  Result      VARCHAR(8) NOT NULL,   -- Pass/Fail/Retest
  LSL_Snap    DECIMAL(12,4),         -- 限值快照
  USL_Snap    DECIMAL(12,4),
  RuleVersion INTEGER,
  JudgeTime   TIMESTAMP NOT NULL
);

建表后应重点验证三件事:一是插入一条测量后,能否仅凭条码查出其序列、步骤、项目与判定依据;二是修改某项目限值后,旧判定结论是否保持不变;三是按“型号+项目+时间段”统计不良率时,查询计划是否走外键索引。若第二点不成立,说明快照字段缺失或版本策略未落实,需要回到判定结论表补冗余。

六、索引与查询路径

追溯查询最常见的入口是产品条码,因此 Measurement 表应在 Barcode 上建索引,并考虑 (Barcode, MeasTime) 复合索引以支持按时间排序回放。按步骤统计时,StepID 外键索引必不可少。Verdict 表通过 MeasID 与测量结果一对一关联,MeasID 上建唯一索引可同时保证一对一约束与查询效率。

需要提醒的是,反规范化字段不要参与高频过滤条件,否则一旦快照与主表不一致,过滤结果会自相矛盾。快照字段的定位是“展示与复现”,不是“检索主依据”。检索仍应走规范化外键,展示时再取快照,这样既保证一致性,又保留追溯能力。

综上,测试数据模型的设计顺序应是:先按实体职责划清边界,用代理主键与业务唯一键分离,用外键串起序列—步骤—测量—判定链路;再在事实表上做有限反规范化,固化限值快照与规则版本;最后用索引支撑条码追溯与统计聚合。这样得到的模型既能正确回答“这台产品当时按什么规则判的”,也能高效回答“这个项目最近的不良趋势如何”。