产线看板实战:UPH、良率、稼动率的口径与坑
背景:看板上三个数字,车间吵了一星期
车间要上电子看板,老板开口就要三个指标:UPH、良率、稼动率。结果一上线就翻车——白班报 UPH 45,晚班说只有 38;品管说良率 99.2%,生产说 97.5%;设备那边又说稼动率才 60%,是设备不行。数据对不上,会上吵了一星期。问题不在采集,在口径没定死。
解决思路:先定口径,再谈实现
看板是给人看的,指标定义不统一,再准的数据都是废的。我的做法分三步:
- 定口径:每个指标写进数据字典,公式、数据源、边界条件全部钉死,全厂只认一份定义;
- 定数据源:指标从哪张表来、谁负责维护,避免生产、品管、设备各报各的数;
- 定性能方案:看板走预聚合,绝不让大屏实时扫流水表。
三个指标的定义:坑都在分母里
先看公式,再看坑:
UPH = 合格产出数 / 实际生产小时
良率 = 合格数 / 投入数
稼动率 = 实际稼动时间 / 计划生产时间
- UPH:分子按"合格产出"算,和良率口径联动;分母的"实际生产小时"要排除计划内停机(换型、保养),否则白班换型两小时,UPH 直接被拉垮;
- 良率:返修品算不算合格?首检、终检、直通率(FPY)必须分开列,别混成一个数;
- 稼动率:停机怎么分类?故障、缺料、换型、待机分开统计,老板才能看出"停在了哪"。
实现:SQL 聚合 + 预计算表
数据源就三张:报工记录表(产量)、设备状态日志(运行/停机/故障)、品检表(合格/不良)。按小时聚合 UPH 和良率的查询:
SELECT CONVERT(varchar(13), report_time, 120) AS hour_key,
COUNT(DISTINCT sn) AS output_qty,
SUM(CASE WHEN result = 'OK' THEN 1 ELSE 0 END) AS ok_qty,
SUM(CASE WHEN result = 'OK' THEN 1 ELSE 0 END) * 1.0 / COUNT(DISTINCT sn) AS yield
FROM dbo.production_report
WHERE report_time >= DATEADD(hour, -24, GETDATE())
GROUP BY CONVERT(varchar(13), report_time, 120)
关键优化是预聚合:后台作业每小时把流水表滚动汇总进 Agg_ByHour 汇总表,大屏只查预聚合结果。看板 30 秒轮询一次,汇总表随便查;直接扫流水表的话,数据量一上来大屏就卡死、锁等待飙升。
前端刷新策略也要分档:分钟级指标用轮询(30s~1min)足够,只有秒级异常告警才上 WebSocket,别什么东西都搞实时推送。
踩坑记录:五个真实案例
- 班次边界重复/漏算:交接班定在 8 点整,设备上报时间差几秒,同一件活被算进两个班。统一用服务端时间截班次,别信工位本地时钟;
- 稼动率算出负数/无穷大:未排产时段计划生产时间为 0,除零直接爆。聚合查询加
NULLIF保护,除数为 0 时按 0 展示; - 良率口径打架:生产按首检算 99%,品管按终检算 97.5%,谁也说服不了谁。最后定:看板默认显示直通率,首检、终检各占一列,数据透明谁也不吃亏;
- 换线时间去哪了:换型 40 分钟算稼动还是算停机?算稼动,稼动率虚高;算停机,生产不服气。最后定成独立分类"换型",三指标之外单独展示,既不影响稼动率也不抹掉工时;
- 大屏 3 秒一刷,数据库扛不住:越刷越慢,流水表锁等待暴涨。改成预聚合 + 30s 轮询后,查询耗时从秒级降到毫秒级。
总结
看板项目的本质是指标治理,不是画图。先把公式、口径、边界写进数据字典并全厂签字确认,再谈 SQL 和前端;数据源固定三张表,展示层只读预聚合结果。口径统一之后,剩下的 SQL 和前端都是体力活——真正难的是让全厂认同一个数。