FDE Times 数据在招 FDE 职位 826▼35 近 7 天在招职位数的变化(同口径比较):不计入本周新开始追踪的公司的职位近 7 天新增 77在招公司 154支持远程 25%美国薪资中位数 $202k招聘最多 Databricks 104
ENVI

前线部署工程师(FDE)的专业媒体

技能指南 · 指南

SnowConvert 部署零报错,恰是迁移最脆弱的时刻

工具改得了语法,改不了语义:空字符串、类型转换和文本分组可能不报错却算错数,只能用数据证明一致。

分享微博

要点速览

  • SnowConvert AI 会用 EWI 和 FDM 标出它自己处理不了的地方,但有些语义差异会改变数字,却不触发任何报错。
  • Oracle 把空字符串当作 NULL;在字符串转数字以及 GROUP BY 中的字符串比较上,Teradata 都比 Snowflake 宽松。
  • 行数一致本身证明不了什么:要比对每一列;对关键表,还要用主键加 MD5 哈希逐行比对。
迁移到 Snowflake 时数据验证的三个层级。每一条横条都比上一条更长,表示成本逐级上升。结构层比对类型、精度和标度;指标层以默认容差 0.001 比对聚合数字;以橙色突出的行级层对每行计算 MD5 哈希,适用于财务表。
Snowflake 的数据验证分三个层级。行级验证成本最高,因此默认关闭,只应对供给财务或监管报告的表开启。来源:Snowflake 数据验证文档。

你已经用 SnowConvert AI 把客户的全部 SQL 资产跑了一遍。脚本部署到 Snowflake 没报一个错,第一块仪表盘已经出数,客户正在问什么时候能关掉旧系统。项目恰恰在这个时候最容易出问题,因为剩下的每一个 bug 都不会触发任何告警。

自动转换工具很擅长处理语法,但无法保证语义,即同一条 SQL 在两个平台上返回相同的结果。在这个阶段,前线部署工程师(FDE)的任务是用数据证明结果确实一致,并在客户关掉旧系统之前把证据摆到客户面前。

工具的警告清单只是起点

对于两个平台之间无法自行解决的差异,SnowConvert AI 会记录为 EWI(错误、警告与问题)和 FDM。Snowflake 自己也建议在部署前审查转换后的代码。人们很容易以为,清空这份清单就算完工。

陷阱在于:有些差异是工具看懂了、却有意不改的;还有些差异只有在代码跑真实数据时才会暴露。把 EWI 清单当作该往哪里看的地图,而不是逐项打勾的待办清单。下面四个方面最值得优先关注。

陷阱 源系统 Snowflake 检查方法
空字符串 Oracle 把 ‘’ 当作 NULL ‘’ 和 NULL 是不同的值 搜索带 ‘’ 的 REPLACE 和 CONCAT
字符串转数字 Teradata 能读取空字符串或全空白字符串 容易出现运行时错误 统计源列中的脏值数量
文本列上的 GROUP BY Teradata 默认不区分大小写 ‘ABC’ 和 ‘abc’ 变成两组 比较两个系统的分组数量
定长 CHAR Teradata 连尾部填充空格一起匹配 CHAR 不补空格 重跑 LIKE 操作和字符串函数

Oracle:空字符串没你想的那么“空”

Oracle 文档写得很明确:长度为零的字符值被视为 NULL。Snowflake 不这样处理,所以 SnowConvert 会把空字符串改写为 NULL,以保留原有行为。大多数情况下,这种改写是正确的。

例外是 REPLACE 和 CONCAT 的参数。SnowConvert 文档说明,这里不做该转换,因为在这些调用里把空字符串变成 NULL 会改变查询结果。看一个规范化客户电话号码的查询:

-- Oracle,转换后保持不变
SELECT customer_id,
       REPLACE(phone_number, '-', '') AS clean_phone
FROM customers
WHERE notes IS NULL;

REPLACE 这一行是有意保留不改的,但你仍然要在两个系统上各跑一遍,确认结果一致。更值得担心的是 WHERE 这一行。在 Oracle 上,IS NULL 也会命中“空白”备注,因为 Oracle 从不存储空字符串。如果数据加载到 Snowflake 后,notes 列里留下了 ‘’,这些行就会悄无声息地从结果中消失。

一条查询,两边对账

第一项检查很简单:对每个重要的文本列,分别统计 NULL、空字符串和只含空白字符的字符串。在 Snowflake 上,查询如下:

-- Snowflake(几乎原样可在 Teradata 上运行)
SELECT
  COUNT(*) AS total_rows,
  SUM(CASE WHEN notes IS NULL THEN 1 ELSE 0 END) AS null_count,
  SUM(CASE WHEN notes = '' THEN 1 ELSE 0 END) AS empty_count,
  SUM(CASE WHEN notes <> '' AND TRIM(notes) = ''
           THEN 1 ELSE 0 END) AS whitespace_only_count
FROM customers;

在 Oracle 上,比较 = '' 永远不成立,因为空字符串本来就是 NULL,所以 empty_count 始终为 0。要在 Oracle 上统计全空白字符串,把条件改为 notes IS NOT NULL AND TRIM(notes) IS NULL。

比对时,把 Snowflake 的 null_count 与 empty_count 相加,再与 Oracle 的 null_count 对照。如果数字不一致,就要回头检查那些按 IS NULL 过滤的查询。

同理,对任何即将用于 GROUP BY 的列,在 Snowflake 上比较 COUNT(DISTINCT city) 和 COUNT(DISTINCT UPPER(city))。两个数字不同,说明该列中有仅大小写不同的值,分组报表就会像下文所述那样与 Teradata 出现偏差。

Teradata:在最意想不到的地方宽松

Teradata 的差异在于容忍度。把字符串转为数字时,Teradata 接受空字符串或全空白字符串,Snowflake 则更严格。一条多年来运行顺畅的 CAST(postal_code AS INTEGER),第一次遇到这类行时就可能出错。错误只在运行时出现,转换阶段看不出来。

GROUP BY 的问题更难发现。Teradata 默认不区分大小写比较字符串(NOT CASESPECIFIC)。除非设置排序规则(collation),否则 Snowflake 会把仅大小写不同的值当作不同的值:

SELECT city, COUNT(*) AS order_count, SUM(total_amount) AS revenue
FROM orders
GROUP BY city;

假设 city 列里同时有 ‘Ha Noi’ 和 ‘HA NOI’。在 Teradata 上它们是一组;在 Snowflake 上,上面的查询会返回两行,按城市统计的收入报表里突然多出一个“新城市”。全表总数依然一致,所以只核对总数抓不到这个 bug。

定长 CHAR 是第三个陷阱。Teradata 会在值的尾部补空格,有些函数会连同填充空格一起匹配整个值。Snowflake 的 CHAR 不补空格,所以 CHAR 列上的 LIKE 操作和字符串函数都需要重跑并比对。

数据验证:三个层级,由便宜到昂贵

代码审查告诉你该怀疑哪里,数据比对才是证据。Snowflake 的数据验证流程分三个层级:结构、指标和行级。行级验证最耗资源,因此默认关闭。

在结构层,比对数据类型、精度和标度。如果源端的精度或标度大于目标 Snowflake 列,流程会在对应层级报告差异。

指标层以默认容差 0.001 比对聚合度量。这个容差对金额列是否可接受,要去问客户,而不是自己假定。

行级检查会在源端为每个分区生成签名,由主键列加整行的 MD5 哈希组成。任何有差异的分区,都会进一步核查到单个单元格。这一层成本很高,因此只对供给财务报告或监管申报的表开启;日志表用指标层就够了。

迁移工具厂商 Datafold 认为,数据类型悄无声息地不匹配,是迁移后出现差异的常见原因,并建议逐列检查,而不只是统计行数。上面的 GROUP BY 例子说明了原因:基础表的行数完全一致,出错的只是分组结果。

在客户现场的工作顺序

先从 EWI 和 FDM 清单入手,按业务重要性而不是警告数量给文件排序。然后在全部转换后的代码里 grep 上表中的四种模式:带空字符串的 REPLACE 和 CONCAT、转为数字的类型转换、文本列上的 GROUP BY,以及 CHAR 列上的字符串函数。

接着,对所有表运行结构和指标检查,再对你和客户商定的一小批“绝不能出错”的表开启行级检查。比对期间冻结已迁移的数据:Snowflake 文档提醒,验证期间不要修改数据,否则验证结果会失真。

最常见的错误,是把“行数一致”当作完工的证明来汇报。其次是直接在目标表里修正差异却不做记录,导致下一轮验证没有可比对的基线。第三是只处理工具标出的问题,忽略工具有意保留不改的地方。

把这段经历变成简历上的亮点

如果你的目标是数据方向的 FDE 或解决方案工程师岗位,迁移经验只有在你讲得清验证工作时才算数。简历上不要写“参与 Snowflake 迁移”这类空泛的话。

写清楚你验证了哪些表、在哪个层级验证、发现了哪些类型的语义差异、又是怎么修复的。看简历的人一眼就能看出,你为数字负了责,而不只是按下了运行工具的按钮。

客户很少记得一次迁移搬了几千行 SQL,但他们会记得 Snowflake 上第一个月的收入报表和旧系统对不对得上。

这篇文章对你有帮助吗?

6 个信源
路线图上的下一篇 · 阶段 5: 部署上线五角大楼项目的 FDE,为何写代码前先问影响等级FedRAMP 只是底线,其上的影响等级决定部署位置、隔离程度和谁能看日志。