不搬数据:一次 SPC 数据架构的取舍

技术选型里最难的部分从来不是「选什么」,而是主动决定不做什么 ——
以及当有人问「为什么不走那条更省事的路」时,你能不能答上来。

一、先说结论

我们在做工业质量分析平台(SPC)时,遇到过一个问题:数据怎么进来。

默认答案是 ETL:把客户的数据抽出来、洗干净、装进平台自己的库,然后在平台里
分析。这是成熟方案,工期可估,出了问题也好排查。

我们没有那么做。

我们做的是:数据留在客户的库里,平台带着分析能力走过去。

这个决定后来改变了整个产品的架构形态。而它当时之所以难,不是因为技术上
更复杂 —— 而是因为走默认路径永远不需要向任何人解释

下面把这个决定完整拆开。


二、场景:数据不在一个地方

制造业客户的质量数据,从来不是集中在一个库里的。

客户现场的数据分散在三类来源:企业数据库、工业现场设备、以及各种数据通信方式 企业数据库 SQL Server · MySQL · Oracle PostgreSQL · MES · ERP 工业现场 PLC · CMM · 传感器 测量设备 · SCADA 数据通信 MQTT · OPC-UA · TCP/UDP HTTP / Web API · Excel / CSV 工业质量分析平台 SPC 分析 · 控制图 · 异常识别 报警 · 过程能力 · 报告

数据源不是「一个数据库」,而是三类完全不同的东西 —— 它们的访问方式、稳定性、权限模型都不一样。

这三类东西的差异,比它们看起来的要大得多:

查询方式 稳定性 谁在管
企业数据库 SQL,可能有连接数限制 稳定,但可能禁止外部直连 DBA / IT 部门
工业现场设备 专有协议,可能需要网关 会断、会重启、会换型号 设备 / 自动化部门
数据通信 推 / 拉模型不同 取决于网络 网络 / 安全部门

这里的模糊点不是「怎么连」,而是「连上之后,数据放在哪」。


三、两条路线,成本差一个量级

「把数据接进来做分析」这句话,可以指两种截然不同的架构:

路线 A 用 ETL 把数据复制进平台再分析;路线 B 让分析能力直接走到客户数据上

A
复制

客户数据库


ETL

平台数据库



SPC 分析

B
走过去

客户数据库


按需读取 · 增量

数据访问层



SPC 分析

A 的终点是「平台里有一份数据」;B 的终点是「平台能算客户的数据」。 看起来只是数据放在哪,实际上决定了后面所有事。

A 的三个代价

ETL 复制的三个代价:存储与成本翻倍、同步时效滞后、以及数据可能不允许出库 01 存储与成本翻倍 客户库里已有的历史检测数据 要在平台里再存一份,且要持续 保持同步 02 时效性滞后 每一次历史追溯,都要等一次 搬运完成 —— 而质量分析经常 要查很久以前的数据 03 可能根本不允许 数据出库。内网隔离、合规要求、 甲方 IT 政策 —— 这些在工业现场 是常态,不是例外

前两个是工程代价,可以估算;第三个是前提性的 —— 它不是「更难做」, 而是「在某些客户那里根本做不了」。

第三条才是决定性的。 前两条是成本问题,第三条是可行性问题。
一个方案的代价如果是「在某些客户那完全不可用」,那它就不是一个通用架构。


四、边界:明确划掉什么

这一步在项目里最容易被跳过,但它恰恰是 FDE 面试里权重最高的考点 ——
先划清范围,再谈方案。

内容
In scope 一个统一的数据访问层 + 标准化测量事件模型 + 多分析引擎共享同一份数据
Out of scope 把客户的全部历史数据复制进平台
Out of scope 为每一个数据源写一条独立的分析链路
Out of scope 要求客户改造网络或数据库以适配平台

最后一条值得单独说:工业软件的部署方案是产品的一部分,不是实施阶段的临时问题。
互联网软件可以要求用户升级浏览器;工业软件不能要求客户改网络架构。


五、目标架构

确定「不搬数据」之后,架构形态就基本确定了:

架构链路:客户原始数据经数据访问层标准化为统一测量事件,再由多个分析引擎共享 客户原始 数据 数据访问层 按需 · 增量 统一测量 事件 分析引擎 多套 控制图 CPK · 报警 一次采集 · 一次标准化 · 多引擎共享

关键不是这条线本身,而是中间那两个方框 —— 它们是唯一知道「原始数据长什么样」的地方。

用当时的话总结这次升级的原则:

能直接用,就不搬;需要持续分析,就增量;需要实时,就走数据流;
一次采集、一次标准化、多分析引擎共享。

第一条改变的是数据的位置,后三条改变的是数据的形状 —— 而这才是真正
难的部分。见下一节。


六、第二个决策:口径只能有一个

系统里同时存在 Python 和 Minitab 两套分析引擎。它们的算法实现不同、
调用方式不同、部署要求也不同。

如果让它们各自去取数,会出现一个很隐蔽的问题:

对比两种做法:引擎各自取数会导致口径不一致;统一测量事件保证结果一致

各自取数

客户数据源

Python 取数 Minitab 取数 口径 A 口径 B

同一份数据,两套结果
—— 而它们本该一模一样

统一取数

客户数据源

统一测量事件 口径一致 口径一致

换引擎不改口径
—— 数据形状只有一个

在质量分析里,「同一份数据算出两个不同的过程能力指数」是灾难 —— 客户不会和你讨论哪套算法对,他会说「这系统不准」。

所以第二个决策是:统一分析接口,让不同引擎共享标准化测量数据。
引擎各写各的,但数据形状只有一个

代价是明确的前期成本:要建模、要定义「统一测量事件」到底长什么样、
要说服各引擎的维护方改接口。这比「各自取数」贵得多。

但它买的是一种不会随时间劣化的性质。 各自取数在第一个月是更快的,
在第 N 个数据源接入时才开始变慢 —— 而那时候改已经来不及了。


七、为什么这个决定难

回头看,这个决定技术上并不复杂。它难在三个地方:

1. 默认路径不需要解释。
ETL 是行业惯例。选它,没有人会问你为什么。
选「不搬数据」,你要向每一层解释:为什么不用更成熟的方案?

2. 它的收益是「不会发生的事」。
ETL 的痛(存储、时效、出库限制)在方案评审时都还没发生。
你要为一个尚不存在的问题提前付出架构成本。

3. 它假设了一个经常不成立的前提。
默认复制隐含地假设:数据的所有权和使用权可以分离。
在工业现场,这个假设经常是错的 —— 数据可能几个亿、客户库里还在持续写入、
网络不通外网、甚至有合规要求不允许出库。

把「复制」从一个默认动作,降级成一个需要论证的动作 ——
这是我在这件事里学到的最有用的东西。


八、结果

架构演进的方向与原则是可以核实的(本文第五节)。
但要按本站的证据纪律说清楚:我无法提供量化结果。

原始材料里没有留下对比基线 —— 没有「查询耗时从 X 降到 Y」,
也没有「支撑了 N 个客户」。我不会为了这一节好看而补一个数字上去。

L1 展示架构演进方向明确;量化协作基线缺失

可以说的定性结果是: 这套架构让「接入一个新数据源」不再意味着
「为它单独写一条分析链路」,而是「为它写一个适配器」——
后者的工作量和前者不是一个量级。


九、复盘:我现在的判断方式

这件事之后,我在做架构决策时会先问三个问题:

① 这个方案的代价,是「更难做」还是「做不到」?
更难做可以估算、可以投入;做不到是硬约束,必须优先处理。

② 这个方案假设了什么前提?
如果前提不成立,方案还成立吗?ETL 假设「数据可以出库」——
这个前提在工业现场经常不成立。

③ 如果 12 个月后数据量翻十倍,这个决定还成立吗?
各自取数在第一个月是对的;统一事件在第 12 个月是对的。
要选那个在第 12 个月仍然对的。


十、和另一个案例的关系

这个决定和本站另一个案例(Minitab COM 桥接)是同一条线上的两件事:

一次决策链的五个环节:场景、模糊点、边界、决策、复盘 场景 模糊点 边界 决策 复盘 本文完整走了一遍这条链 —— 面试官要读的正是它,而不是技术栈

两篇文章是同一个模式:约束 → 模糊 → 划边界 → 在 ≥2 个备选里取舍 → 复盘。

接入层解决的是「单个分析能力怎么进系统」;
架构层解决的是「所有分析能力怎么共享同一份数据」。

后者是前者的前提 —— 如果数据形状不统一,接进来的能力越多,系统越乱。


关于本文的证据

L1 展示架构演进方向明确;量化协作基线缺失

可以被核实的:本文描述的架构演进方向(从 ETL 复制到数据访问层 +
统一测量事件)与取舍原则,来自我实际参与的产品工作,原始表述存档在
本站仓库的 tools/RESUME-SOURCE.md

我不能提供的:量化结果、客户名称与部署细节。
前者原始材料里没有,后者需要确认能否公开。

关于文中的图:全部是我为本文绘制的解释性示意图
用来表达架构逻辑,不是产品截图,也不含客户数据。它们用内联 SVG 绘制,
因此能跟随明暗模式,也不需要依赖任何外部图床 ——
这一点我特意做过:本站另一个案例的演示视频曾外链在第三方服务器上,
后来那个链接失效了。

相关阅读作品与证据 · 简历