MUMPS(又称 M)支撑着 Epic。支撑着 VistA。支撑着你在不知情的情况下接触的全球医疗栈的大片领地。它今年60岁,语法让 Perl 最糟糕的日子也显得优雅,但它是——毫无疑问——我用过的最快的层级键值存储。每次我在会议上提起 MUMPS,总有人笑出来——然后发现我是认真的。
MUMPS 到底是什么
MUMPS 同时是两件事:
- 一门编程语言,1966年设计,变量隐式声明,单字符命令,控制流模型早于结构化编程。冷读 MUMPS 代码是一种体验。
- 一个层级数据库,以
^globalName(subscript1, subscript2, …)寻址,默认持久化。写入一个 global 就是磁盘写入。读取就是磁盘读取。语言和数据库焊在一起;没有”ORM”,因为程序直接在数据结构上操作。
结果是:一个写得好的 MUMPS 程序可以在90年代的单核上每秒做几千次操作而毫不费力。存储引擎效率惊人,因为写它的人认为64 KB 内存是奢侈品,并以此为前提进行了设计。
为什么它在2026年依然在用
显而易见的问题是:为什么还有人在用这个?几个没人写博客谈的原因:
- 它极其可靠。 global 存储模型是事务性的,崩溃安全。运行了30年没有数据丢失事故的 MUMPS 安装不是稀奇——是常态。
- 代码+数据的同处是性能武器。 现代三层架构每次数据库访问都要付一次往返成本。MUMPS 不付——数据结构从执行代码行就可以直接寻址。对于小读写密集型工作负载(比如:药房查询、患者病历访问、实验室结果写入),它在真实世界的 benchmark 里依然能打过大多数东西。
- 迁移成本令人恐惧。 Epic 的代码库积累了40年。完整重写不是18个月的项目;是几十年的项目。正确的战略问题不是”我们什么时候替换它?“而是”我们在它旁边建什么?“
在它旁边工作的所得
在 HAKEEM,我们遇到了 VistA/MUMPS 组件,因为约旦公共卫生 IT 采用了美国退伍军人事务部开源医疗栈的部分组件。在 AFAQ,我们与药房系统集成,其数据层是类 MUMPS 的。我不声称自己是 MUMPS 专家——在那些年里我大概写了几千行它的代码。我确实声称的是,那几千行教给了我的数据库设计知识,超过了我之后做的大量现代 RDBMS 工作。
具体来说:
- 下标键设计比你想象的更重要。 选择正确的键层级是 MUMPS 版本的 schema 设计。搞错了,读取会扫描太多。搞对了,你拿到 O(1) 访问到你要的精确字节。
- 成本模型在代码里是可见的。
SET ^patient(id, "name")=value就是磁盘操作。你无法把这隐藏在 ORM 后面。这迫使你在一个现代语言鼓励你忽略的层面上思考数据访问。 - 全局锁是特性,不是 bug。 MUMPS 的锁模型是原始的,这意味着你可以推理它。现代分布式锁是复杂的,这意味着你推理不了。
2026年的版本
如果我在2026年从头开始做一个全新的事务性医疗系统,我会选 MUMPS 吗?不会。我会用 Postgres 加精心的 schema 设计和明确的事务边界,过得更舒适。
但我也会拒绝嘲笑那些在生产中还在跑 MUMPS 的代码库。它们是医院系统中承重的部分,让人们活着。维护它们的工程师的技能是不成比例地扎实的,而现代 Web 工程师并不认识这种扎实:他们在字节层面理解存储成本,他们能推理几十年前的不变量,他们与生产数据的关系是 FAANG 工程师20年前就失去的那种。
那句引用
如果你团队里有人嘲笑一个 MUMPS 代码库,他们告诉你的是他们自己的事,不是代码库的事。问问他们上次的全新重写在生产中跑了多少年。如果答案是”没有”,那么笑声是过早的。
还在跑生产的最老的代码,几乎总是最不值得嘲笑的代码。