
1. 先把“稳定”和“新版”这两个词拆开看FME 这套数据集成工具干的是格式转换、空间数据处理、批量 ETL 这类脏活累活。项目里最常见的场景是一批 CAD 图纸要转成 GIS 图层几个部门的表格要按空间关系挂到地块上或者每天凌晨定时从数据库里抽数、清洗、落成标准成果。它不产出炫酷的可视化但只要数据交付流程依赖它版本一动整条链路的输出结果就可能跟着动。我所在的团队常年维护一批跑了好几年的工作空间Workspace2018 和 2020 这两个版本一直并存一部分交付环境锁在 2018一部分新项目上了 2020。这中间踩过的坑足够写一篇东西了。所以这篇文章不聊“新版本有什么新功能”这种官方说明式的罗列而是站在一个要天天维护模板、要保证输出结果一致的人的角度把这两个版本的差异、并行安装怎么弄、迁移怎么迁、性能到底差多少一条条摊开讲。先说结论的方向2018 的价值在于“确定性”2020 的价值在于“少折腾”。这两个词听起来都对但落到具体项目上取哪个,要看你手上那批工作空间的历史很长还是你更怕后面几年被旧环境拖死。1.1 2018 到现在还被人抱着不放原因很实在我接触过的环境里继续用 2018 的理由高度集中基本就四类。第一类是交付环境锁定。上级单位或者协作方给的验收环境就是固定版本你本地升了也没用成果提交过去人家那边打不开或者跑出来不一样返工成本比升级成本高得多。这种情况下版本不是技术选择是协作契约。第二类是历史资产太厚。一个跑了五六年的模板库几百个工作空间里面嵌着几十个自定义转换器Custom Transformer还有一堆 PythonCaller。这些资产在 2018 里是“能跑”的状态一旦升级谁也不敢保证全都能跑而且没人有空做全量回归。第三类是 Python 2.7 依赖。2018 里内置的解释器还是 Python 2.7 那一代很多老的自定义脚本是按那个环境写的。字符串编码、除法行为、字典遍历顺序这些细节在 Python 3 下会变。这些脚本往往没有版本管理也没有单元测试改起来心里没底。第四类是 32 位插件依赖。有些年头久一点的第三方组件、老的数据库客户端只提供 32 位版本而较新的安装包只给 64 位。这一条卡死了不少还在用老设备驱动的环境。这四类理由没有一个是“技术上更先进”全是工程约束。所以别一听别人说“新版更好”就急着劝人升级先问清楚他属于哪一类。1.2 2020 真正值钱的地方不在功能列表上2020 相比 2018 跨了两个大版本号中间的变化不是加几个转换器那么简单。我实际用下来真正影响日常效率的是这么几块内置 Python 从 2.7 那一代跨到了 Python 3.7 一代。这件事的正面价值是巨大的第三方库生态、字符串处理、异步写法全都跟得上现在的习惯了负面价值也同样巨大就是所有老脚本必须过一遍。这个后面单独开一节讲。工作台和调试体验的重做。数据检查器Data Inspector在 2020 里对三维、点云、栅格的渲染明显更顺看一条线的属性不用来回切换窗口。工作空间画布支持书签式的组织方式大模板拆成几个区域之后找转换器不用靠滚轮硬拉。格式驱动的版本更新。新版对较新的地理数据库版本、较新的 CAD 文件版本、GeoPackage 和 GeoJSON 的读写兼容性都更完整。这个差异在你处理外部来料的时候特别明显——别人给你一份新版本软件导出的文件2018 可能读得进但字段类型判断出错2020 一般不会。服务端和批处理侧的成熟度。任务队列、资源分配、容器化部署这些东西2020 那一代明显比 2018 顺畅尤其是要跑上千个工作空间任务的场景。注意以上都是我这边的使用感受不是官方基准。不同操作系统、不同驱动版本下结论可能反过来所以后面第 4 节我给的是“怎么测”而不是“照抄我的数字”。1.3 我这次对比用的口径先说清楚免得误读版本对比最容易出的问题是拿两个不同数据、不同机器、不同参数的结果硬比然后得出一个看起来很有说服力的结论。这种事我见过太多次。我这次的做法是同一台机器16 核 CPU、64GB 内存、NVMe 固态硬盘、同一个操作系统版本两个版本安装在不同盘符下同一份自建压测样本避免用真实业务数据也避免数据本身有脏值导致某一版报错中断同一套工作空间逻辑2018 和 2020 各存一份转换器顺序、参数值尽量对齐凡是有默认值变化的参数全部显式指定每个用例跑三次取中位数跑之前清掉系统文件缓存干扰记录的不只是耗时还有峰值内存、临时文件大小、日志里出现的警告条数。这么设计的原因很简单单看耗时缓存一命中就能差出一倍结论没法看单看能不能跑通又体现不出长事务下的稳定性差异。只有把耗时、内存、告警三个维度一起看才勉强能反映“这个版本在我这套流程上是什么表现”。2. 并行部署让 2018 和 2020 住进同一台机器很多人不敢升级的真实原因不是不想用新版是怕装了新版之后旧环境坏了回不去。这个担心完全合理因为这类桌面工具在安装时确实会写系统级的共享组件、注册表项和文件关联。解决办法不是“小心一点”而是按隔离的思路安装两个版本各占各的目录、各用各的许可配置、各管各的文件关联。2.1 装之前先做的四项检查别急着点安装包先花十分钟确认四件事能省下后面几小时的排查。第一确认旧版本的安装路径和许可文件位置抄下来。特别是浮点许可Floating License的服务器地址和端口以及本地固定许可的授权文件存放目录。这两样东西丢了重装一次能让人崩溃。第二确认工作空间和自定义转换器的仓库位置。这类工具通常有一个“共享目录”的概念自定义转换器、自定义格式、启动脚本都放在里面。如果两个版本共用同一个仓库新版本可能会在打开旧工作空间时自动“升级”里面的组件把旧环境搞坏。这是最阴险的坑因为它是静默发生的。第三确认机器上有没有旧的数据库客户端、CAD 运行库、Python 发行版。这些东西是共用的新装一个版本的运行库有可能覆盖掉旧的导致 2018 里本来正常的读取突然报错。第四确认磁盘空间。两个完整安装包加各自的临时目录和缓存预留 30~40GB 比较稳妥。临时目录尤其容易被忽略处理大文件时临时文件体积可能是源数据的两三倍。2.2 隔离动作把“共用”改成“各用各的”我采用的隔离方案是这么几条实测下来两个版本互不干扰隔离项2018 的处理2020 的处理目的安装目录独立盘符下的独立文件夹另一个独立的顶层文件夹避免同名 DLL 互相覆盖自定义仓库指向旧仓库设为只读复制一份到新路径指向副本防止新版静默改写旧组件临时目录单独指定一个目录单独指定另一个目录避免大文件互相挤占和锁冲突许可配置保持原有服务地址单独配置不回写全局防止许可被覆盖文件关联保留.fmw默认关联不动关联通过快捷方式启动双击打开时不会误用版本具体的操作顺序是先装旧版如果已经装了跳过确认旧版能正常启动、能打开一个典型工作空间并跑通再在完全不同的路径下装新版装完之后立刻把新版的共享仓库路径改到副本目录不要用默认的公共路径。这里有个细节值得单独说共享仓库路径一定要在装完、还没打开任何工作空间之前就改掉。因为这类工具在首次启动时会做一次“仓库扫描”如果扫到旧组件可能直接就按新版本的格式改写了。等已经被改了再改路径来不及。2.3 许可配置按什么顺序做许可这块不同版本的管理形态有变化新版带了独立的许可管理向导旧版更多依赖安装时配置或者手动指定许可服务。所以顺序很重要先把旧版的许可确认可用跑一个最小工作空间验证再装新版用新版自带的许可向导配置配置时明确选择“不修改已有配置”配完立刻启动一次新版看许可状态是否正常再回头启动旧版确认旧版许可没被动过。这四步做完基本可以确认两个版本的许可互不影响。如果第三步发现新版把旧版许可顶掉了别慌把旧版的许可服务重新指向原来的地址即可一般不需要重装。提示许可这块最容易出的问题是“笔记本换网络环境后许可失效”。带许可的机器在办公室和家里来回切网络时浮点许可如果依赖主机名解析很容易失败。我的做法是在许可配置里一律用固定地址不用主机名省掉一半的无谓排查。2.4 卸载和回滚留一手回滚这件事靠的不是卸载是在动手之前做一份可恢复的快照。我的习惯是装新版之前把旧版的安装目录整体复制一份到备份盘把许可文件和仓库目录也一起复制。这看起来土但真出事的时候把备份目录换回去、重新指向一下十分钟就能恢复比对着日志猜问题快得多。另外提醒一句不要依赖“卸载新版就能恢复旧版”这个假设。卸载程序清掉的是它自己的文件被它覆盖掉的共享组件不一定会还原。这个坑我在早期版本上吃过一次从此以后一律先备份。3. 核心能力差异哪些会真的改你的工作方式前面说的是部署层面的事。真正决定你要不要切的是日常工作里那些天天碰的东西工作台好不好用、脚本怎么写、外部数据能不能读进来、服务端跑不跑得动。这一节挑影响最大的四项展开。3.1 工作台交互调试时间能省一半老版本的工作空间画布是“一镜到底”的几百个转换器铺开之后找东西全靠记住位置。2020 里加了分区和书签的组织方式一个大模板可以按“来料读取—清洗—空间运算—成果输出”拆成四个区块区块之间还能折叠。这个改动看起来像是界面美化实际影响的是排错效率——日志里报某个转换器出问题你能在两秒内定位到它而不是滚动半分钟。数据检查器的差异更明显。2020 里属性表可以固定列宽和排序规则看一条线要素的几十个字段不用横向拖三维视图和栅格渲染的性能好很多处理几百万点的点云时旋转不卡对同一批要素反复查看时视图状态能保留。还有一个不起眼但很实用的变化转换器参数面板会显示哪些参数被改过。老版本里你打开一个别人写的模板参数一大堆根本看不出哪些是默认值、哪些是人手动调过的。新版会有标记交接模板的时候省掉大量沟通。3.2 Python 运行时迁移成本的大头在这这一条是我认为 2018 到 2020 之间最需要重视的差异。老版本内置的解释器还是 Python 2.7 那一代新版本内置的是 Python 3.7 一代。这两个之间不是“小升级”是语法和生态的断代。实际会踩到的点我列几个最常见的打印语句。老的print xxx写法在 Python 3 里直接语法错误必须改成函数调用形式。字符串与字节串。Python 3 里这两者界限很清楚老代码里那种随手混用的写法会报类型错误尤其是处理中文路径和 GBK 编码文件的时候。字典遍历顺序。Python 3.7 之后字典保持插入顺序但老代码里如果有依赖“遍历顺序随机”的隐式逻辑比如取第一个键当主键升级后行为会变只是它不报错属于安静的错误。除法的整型行为。整数相除在 Python 3 里返回浮点涉及索引和坐标计算的地方要逐个检查。第三方库的版本。老的库可能有 Python 2 专用的轮子新版环境里装不上或者装上之后 API 变了。我的做法是先把所有 PythonCaller 里的代码抽出来放到独立的脚本文件里用目标解释器单独跑一遍不依赖工作空间。这样跑通之后再嵌回工作空间能排除掉大量环境耦合问题。抽代码的过程本身也是梳理逻辑的过程有些脚本写了三四年没人动过正好借机清理。注意新版对 Python 3 的支持不止内置解释器一种方式还可以指定外部解释器环境。如果你的脚本依赖比较重的第三方库比如科学计算那几个建议用外部环境的方式把依赖隔离在自己的虚拟环境里不要往内置环境里装东西否则换机器部署时非常难受。3.3 格式与驱动外部来料的第一道关格式支持这块的差异不是“新版支持、旧版不支持”而是“新版对较新的文件版本判断更准”。举个我实际遇到的例子协作方给的文件地理数据库是用比较新的软件版本创建的2018 打开时字段类型识别有几处偏移日期字段被当成了字符串长整型被读成了短整型同一份数据在 2020 里读出来类型是对的。这类问题最麻烦的地方在于它不报错。工作空间跑完了成果也输出了但类型不对下游做关联的时候主键匹配不上或者日期排序全乱。等你发现的时候已经过去好几天了。我的处理原则是凡是对外接收来料一律先用新版做一次“读取样本检查”把读出来的字段类型和源数据说明对比一遍确认没问题再把数据交给旧版去跑。这样既不改变旧版的处理逻辑又把最容易出错的一环挡在了前面。另一个差异在 CAD 文件上。较新的 CAD 文件版本里有一些新增的实体类型和扩展数据老版本读进来会丢信息新版一般能保住。做图纸转换的团队要特别注意这一条丢掉的往往是标注和块属性这类关键信息。3.4 服务端和批处理任务量大了才看得出差别单机跑一个工作空间的时候两个版本的差别感受不强。但如果是几百上千个任务排队跑服务端这一侧的差异就出来了。2020 那一代任务队列的调度更细可以按工作空间分组设置并发上限资源监控页面能看到每个任务的峰值内存和耗时曲线日志的检索做得更好能按任务 ID 直接拉到对应的运行日志。这些在 2018 里也有但用起来没那么顺手尤其是排查“某个任务偶发失败”这类问题时日志翻起来很累。容器化部署的成熟度也是这一代拉开差距的地方。旧版时代把桌面端和服务端部署到容器里配置和许可都挺别扭新版这块顺畅不少做环境标准化的时候能省很多事。4. 实测对比性能、稳定性和兼容性到底怎么样这一节给的是我这边自建压测样本的结果。再强调一次数字只在同一台机器、同一份数据上有意义你搬到自己的环境里可能差很多。真正有价值的是测试方法拿过去改改就能用。4.1 压测样本怎么造出来的我不想用真实业务数据一是合规二是真实数据里的脏值会让某一边直接报错测出来的不是性能问题。所以自建了三组样本样本 A面状图层约 40 万个多边形28 个属性字段包含中文名称、日期、编码三种类型模拟常见的行政区、地块类数据。多边形顶点数量分布做成长尾大部分是几十个顶点少量上千顶点用来测几何处理的稳定性。样本 B线状图层约 120 万条线要素38 个属性字段模拟路网、管线类数据。这个样本主要测读写吞吐和长事务内存。样本 C混合格式转换把样本 A 和样本 B 分别转成另外三种格式其中一种带坐标系变换一种带属性映射和字符串清洗用来测格式驱动的开销差异。每组样本生成两份完全一致的副本一份给 2018一份给 2020避免文件被占用产生干扰。内存占用的估算我用了这么个思路你可以套到自己的场景里单批要素的常驻内存 ≈ 要素数 ×几何估算字节 属性字节 每要素对象开销。以样本 B 为例每条线平均 3 个顶点每个顶点点位按 16 字节算大约 48 字节属性 38 个字段平均折算下来 120 字节左右对象自身的开销按 300 字节估一条要素约 470 字节120 万条就是 5.6 亿字节约 540MB 的裸数据。但实际运行时还要叠加上读取缓冲、分组缓存、写入批次缓冲峰值到 1.5~2GB 是正常的。这个估算的意义在于如果你机器的可用内存低于这个数的两倍就必须靠分组处理来压峰值别指望一次读完。4.2 读写耗时差异有但没到“换了就飞起”的程度样本 B 从一种矢量格式读到另一种矢量格式带属性直通、不做几何运算三次取中位数用例2018 耗时2020 耗时差异说明样本 B 读取约 112 秒约 96 秒约 14% 提升字段类型判断更快样本 B 写出约 148 秒约 118 秒约 20% 提升批量写入批次更合理样本 B 读写约 261 秒约 210 秒约 20% 提升端到端样本 A 面要素读写约 190 秒约 172 秒约 9% 提升差异不大样本 C 带坐标变换约 340 秒约 268 秒约 21% 提升变换环节进步明显样本 C 带属性清洗约 205 秒约 163 秒约 20% 提升字符串处理快解读一下这些数提升主要来自批量 I/O 的批次策略和字符串处理不在几何计算上。几何运算那部分两个版本基本打平说明核心几何引擎没有大改。所以如果你的流程瓶颈是“读取少量运算写出”新版能省的时间是看得见的如果瓶颈是“复杂空间叠加、缓冲区、网络分析”这类纯几何运算别指望换版本能救得优化算法和索引。还有一个现象值得说新版在小文件上反而可能略慢。几百条要素的小文件2018 大概 3 秒跑完2020 要 4 秒左右主要是启动和初始化的开销更大。所以如果你的场景是大量小任务高频调用切版本前先测一下单位任务的固定开销别被大文件的提升误导。4.3 长事务和内存这才是老版本真正的痛点我的观察是长时间运行的批量任务里2020 的内存曲线更平。具体表现是跑两三个小时之后2018 的峰值内存会缓慢爬升中间夹着几次明显的尖峰偶尔出现“处理到某个环节卡住十几秒”的现象2020 的曲线整体更平滑尖峰幅度小一些。这个差异在数据量接近机器内存上限的时候特别致命。样本 B 放大到两倍之后2018 在一台 32GB 的机器上跑到后半段开始频繁换页任务没失败但耗时从 4 分钟变成 15 分钟同样的任务在 64GB 机器上2020 全程稳定在 2.6GB 峰值左右2018 峰值在 3.4GB 附近波动。所以我的工程建议是别只看平均内存要看峰值和爬升趋势。跑一个长任务把内存曲线截下来看它是不是一路向上不回头。如果是那这个版本的垃圾回收或者缓存释放策略跟你的数据形态不合靠加内存只能拖延不能根治。长事务还有一个容易被忽略的点临时文件。处理大文件时两个版本都会往临时目录写中间结果但体积不一样。我测下来同样一份样本2020 的临时文件总体积略小一些。这个差异在磁盘紧张的环境里很要命尤其是默认临时目录放在系统盘的时候跑到一半磁盘满导致任务失败日志里还看不出明确原因。4.4 兼容性向上兼容这件事比想象中麻烦“新版本能打开旧版本的工作空间”这句话是对的但只说了一半。能打开不等于跑出来一样。我实测了 30 个工作空间从 2018 迁移到 2020结果是28 个能打开并跑通但其中 9 个的输出结果与旧版有差异2 个打不开原因是引用了已经不推荐使用的组件。那 9 个有差异的按原因分类5 个是转换器参数默认值变了。最典型的是空值处理策略和字段类型推断的策略新版更“聪明”会主动把看起来像数字的字符串转成数字这跟旧版的行为不一致。2 个是日期格式的处理。同一个日期字符串两个版本解析出来的时区或者格式串不同落到成果里就是排序错乱。1 个是字符编码。中文路径或者含特殊字符的属性新版默认用 UTF-8 处理旧版沿用本地编码导致某些字段出现乱码。1 个是排序稳定性。多个要素按同一字段排序两个版本在值相同的记录上的相对顺序不同基于这个顺序做的“取第一条”逻辑结果就变了。打不开的那 2 个一个引用了被标记为不推荐使用Deprecated的转换器虽然还能用但会告警另一个用了老版本的自定义格式定义新版不再识别那个配置格式。这些差异说明一件事兼容性验证不能只看“跑通没跑通”要看“输出跟原来一不一样”。具体怎么做下一节给一套可执行的流程。5. 迁移实操把 2018 的工作空间搬到 2020迁移这件事最怕的是“一次性全搬”。我的做法是分层、分批、带回归。下面这套流程在团队里跑过两轮能落地。5.1 第一步资产盘点先搞清楚你手上有什么别急着开工具先做一个表格把资产列清楚。需要盘的东西工作空间总数以及每个工作空间的调用方是谁手动跑、定时任务、服务端接口、别人集成调用自定义转换器的数量和被引用次数被引用超过五次的优先处理带 Python 的工作空间数量以及脚本里用了哪些第三方库依赖特定格式驱动的工作空间尤其是 CAD 和较新版本数据库的连接有明确交付标准的成果这些是回归验证的重点。盘点完你会发现一个规律真正重要的、天天跑的工作空间可能只占三成剩下的是一次性任务或者早就废弃的。先把那三成做透剩下的批量过一遍就行。这个判断能砍掉大量无效工作。5.2 第二步分批迁移从“最不可能出问题”的开始我分的批次是这样的第一批无脚本、无自定义转换器、格式简单的纯转换任务。这一批的目的是验证安装、许可、格式驱动这些基础设施是对的出了问题好定位。第二批带自定义转换器的工作空间。迁移前先把自定义转换器复制一份到新仓库逐个在 2020 里打开、保存、跑通。这一步会发现一批“组件内部参数默认值变化”的问题。第三批带 Python 的工作空间。这批按前面说的办法先把脚本抽出来单独跑通再嵌回去。第四批对接服务端或者被外部系统调用的工作空间。这批放最后因为涉及接口契约改动的影响面最大。每一批迁完立刻在 2020 里跑一次并且跟 2018 的输出做逐项比对不要攒到最后一起比。5.3 第三步参数变更逐个显式化别信默认值前面说的 9 个有差异的工作空间处理办法都是同一个思路把靠默认值决定行为的参数全部显式写出来。具体到操作上我会对每一个关键转换器做这几件事在新版里打开参数面板看看哪些参数被标了“已修改”对照旧版把旧版实际生效的值手动填进新版即使它跟新版的默认值一样对涉及空值、类型推断、日期解析、字符编码的参数必须显式指定一个都不能留默认对有排序行为的操作明确指定排序字段和稳定性要求。这件事麻烦但收益很大显式化之后的模板跨版本行为一致未来再升级也容易。而且显式化之后模板的意图变得清楚交接给别人的时候不用再解释“这里为什么这么设”。提示空值处理和类型推断是两个最容易埋雷的参数组。我的经验是把所有“允许自动转换类型”的选项一律关掉宁可让任务报错也不要让它安静地转错。5.4 第四步回归验证清单照着做不会漏对比输出的时候不要只看“条数对不对”。我用的清单是这么几项检查项怎么查判定标准要素总数统计两边输出的记录数必须完全一致字段结构对比字段名、类型、长度、精度完全一致类型不能放宽几何有效性检查空几何、自相交、闭合性有效性比例一致误差范围内坐标精度抽查若干要素的坐标值小数位误差在可接受范围内属性值抽样按主键抽取 200 条逐字段比对无差异排序结果按业务排序字段检查首尾各 50 条顺序一致字符编码抽查中文属性、特殊字符属性无乱码、无截断日志告警对比两边运行日志的告警条目新增告警必须有合理解释按这个清单走一遍基本能把安静的错误挡住。特别是字段结构那一项很多人只看条数对不对就放过了结果下游关联时主键类型不匹配查半天。6. 常见问题排查实录下面这些是我和同事在并行运行两个版本的一年多里反复遇到、反复被问到的。6.1 启动和许可类症状一装完新版之后旧版启动报许可错误。基本是许可配置被覆盖了。处理顺序是先把新版关掉检查旧版的许可配置指向是否还是原来的地址如果被改了改回去改回去之后如果还报错重启一下许可服务再试。预防办法是安装时一律选择“不修改已有许可配置”。症状二换个网络环境之后两个版本都启动不了。多半是许可校验依赖主机名解析换网之后主机名对不上了。我的解决办法是把配置里所有依赖主机名的地方改成固定地址或者在本机做一条静态解析记录。这个改动一次后面换环境省心很多。症状三新版能启动但一打开工作空间就卡住。先看共享仓库路径是不是指到了旧仓库。新版扫描旧仓库时可能触发大量的格式升级动作看起来像卡死。把仓库路径改到副本目录再重启试。6.2 运行和结果类症状一任务跑完了成果条数对但下游说字段类型不对。这就是第 3.3 节说的问题多半是类型推断策略差异。把类型判断相关的自动选项关掉显式声明字段类型。症状二同一个工作空间两边跑出来的排序不一样。排序稳定性差异。解决方式是显式加一个唯一的次要排序字段比如主键让顺序确定下来。凡是依赖“取第一条”的逻辑都必须这么改。症状三中文属性在成果里出现乱码。编码问题。新版默认走 UTF-8旧版可能沿用本地编码。检查读取和写出两端的编码设置显式指定不要依赖默认。症状四任务跑一半内存暴涨然后被杀掉。先按 4.1 节的方法估算裸数据量看是不是本来就超了可用内存。如果是必须改成分组处理把单批要素数压下来。如果数据量不大还暴涨检查是不是有转换器在做全量聚合比如把所有要素聚成一个集合这类操作会把峰值顶到天上去。症状五处理到某个环节突然卡十几秒。这类间歇性卡顿通常是临时目录 I/O 的问题。看一下临时目录所在磁盘的可用空间和是否跟系统盘同盘换到独立的固态盘上通常能解决。另外检查是不是有格式驱动在做在线校验。6.3 排查速查表现象优先怀疑快速验证方式旧版启动许可报错许可配置被新版覆盖检查许可地址改回后重启服务打开工作空间卡住共享仓库指向了旧目录改路径到副本目录后重启输出类型不对类型推断自动开启关闭自动推断显式声明类型排序不一致排序不稳定补上唯一次要排序字段中文乱码编码两端不一致显式指定读写编码内存暴涨全量聚合或单批过大改分组压单批要素数间歇卡顿临时目录 I/O换独立磁盘查可用空间全新能跑旧不能跑引用了不推荐使用的组件查看日志告警逐个替换7. 到底怎么选按你的处境分场景给建议绕了一圈回到最初的问题。我的看法是这不是一个“技术先进性”的问题是一个“风险放在哪一端”的问题。7.1 这些情况别折腾留在 2018如果你的交付环境被外部锁定成果必须由旧版本产出才能通过验收那就别在主链路上动版本。这种情况下去升级收益全在自己这边风险全在交付那边不划算。如果你的模板库规模很大但调用频率很低一年跑几次那种迁移的投入产出比也很差。这种资产正确的处理方式是“冻结隔离”把旧版本单独装在一台机器或者一个虚拟环境里专门用来跑这些老任务日常办公全用新版。两套环境物理隔开谁也别影响谁。如果你有大量依赖 Python 2.7 的自定义脚本而且这些脚本没有版本管理、没有测试、原作者已经不在那迁移成本会远超预期。这种情况下更务实的选择是先给这些脚本补测试把行为固定下来再考虑迁移。补测试的过程本身可能要花几个月急不得。如果你的工作链条里有 32 位专用组件先确认新版有替代方案没有就老实待着。7.2 这些情况早切早省事新项目、新模板没有历史包袱的直接用新版没有任何理由从旧版本起步。这一点上我很坚决新建的东西用旧版本等于主动给自己挖一个两年后必须填的坑。如果你们的痛点是“外部来料读进来类型不对”“三维和点云看不动”“服务端任务排队排到天亮”那新版在这些方面的改进是实打实的值得为它付出迁移成本。如果团队里新人多教学成本也是一个考量。新版界面和调试工具的引导性更好新人上手快老版本里很多靠口口相传的操作习惯新版有更直观的提示。如果你的自动化流程要做环境标准化、容器化部署新版这条路顺畅得多。7.3 两个版本并行时的团队约定最后说几条并行的约定这些是踩出来的不是想出来的。第一条模板文件必须标注适用版本。文件名或者文件夹结构里明确写清楚不要靠“我记得这个是旧版的”来管理。我们现在的做法是按版本分目录目录里再按业务分。第二条共享组件一律复制不共享。自定义转换器、自定义格式这些东西两个版本各存一份谁也别指向对方的目录。改了一边必须同步另一边的时候走手动合并流程不要做软链接或者自动同步。第三条谁升级谁负责回归。升级工作空间的人负责跑一遍第 5.4 节的清单对比结果留档。这条约定拦下过好几次“以为没问题”的改动。第四条保留一台旧版机器当“参照物”。所有有争议的输出差异拿这台机器跑一遍定论。这比对着文档吵架效率高多了。第五条新任务默认用新版需要旧版必须写理由。这条是防止旧版本环境无限膨胀的。我个人在实际操作中的体会是版本这件事最忌讳的是“两头都想要”既想要新版的体验又不愿意承担一次性的迁移成本。真正省事的路径是明确地把新老环境切开把历史资产当成需要长期维护的“遗留系统”单独供起来新东西一律在新的地基上做。切换的那一刻会有集中投入但之后每一天都在省心。反过来说如果一直模糊着用两个版本混在一台机器上互相污染配置出问题时你连“是不是版本导致”都判断不了那才是真正的麻烦。