3、数据质量与清洗基础:数据质量维度与清洗策略

数据质量这事儿,我做了十几年ETL,感触特别深。

很多人觉得ETL就是写写SQL、跑跑任务。其实不然。你数据质量搞不好,后面报表全是错的,业务部门追着你骂。我见过太多项目,上线第一天就崩,原因就是数据质量没把住。

说白了,数据质量是ETL的命根子。今天咱们就把这块掰开揉碎了讲清楚。

3.1 数据质量的四个核心维度

数据质量不是玄学,它有具体的衡量标准。我个人习惯用四个维度来卡:完整性、准确性、一致性、时效性。

3.1.1 完整性

完整性,就是数据有没有缺胳膊少腿。

举个例子。用户表里,手机号字段是必填的。结果你发现10%的用户手机号是空的。这就是完整性有问题。

我在项目中遇到过最夸张的一次:某电商订单表,订单金额字段居然有30%是NULL。后来一查,是上游系统某个版本升级后,字段映射丢了。嗯,这种坑,你光靠肉眼根本看不出来。

完整性检查的常见场景:
  • 必填字段是否为NULL或空字符串
  • 主键是否唯一、是否有重复
  • 外键关联是否存在(比如订单表引用了不存在的用户ID)
  • 时间戳是否缺失

3.1.2 准确性

准确性,就是数据对不对。

数据是填了,但填错了,比没填更可怕。你想想看,用户年龄填的是200岁,这明显不对。或者订单金额明明是100块,结果存成了10000块。

我曾经接手过一个金融项目。交易流水里,有一批数据的时间戳全部是1970-01-01。为什么?因为上游系统时间戳字段用了默认值0。这种数据要是直接进数仓,那风控模型直接废了。

我常用的准确性校验手段:
  • 值域检查:年龄0-150,金额大于0
  • 格式校验:手机号11位,邮箱包含@
  • 业务规则:下单时间不能晚于发货时间
  • 统计异常:平均值、标准差超出合理范围

3.1.3 一致性

一致性,说白了就是同一个东西,在不同地方得长一个样。

比如用户性别,A系统存的是"男/女",B系统存的是"1/0",C系统存的是"M/F"。你把这些数据合并到一起,就乱套了。

我记得有一次做数据仓库整合,客户信息来自三个不同系统。同一个客户,在CRM系统里叫"张三",在订单系统里叫"张先生",在客服系统里叫"zhangsan"。你说这怎么关联?

一致性问题的典型表现:
  • 同一实体在不同系统中的编码规则不同
  • 度量单位不统一(斤 vs 公斤,元 vs 分)
  • 时间格式不一致(YYYY-MM-DD vs YYYY/MM/DD)
  • 枚举值定义冲突

3.1.4 时效性

时效性,就是数据得及时。

你做个实时大屏,结果数据延迟了2小时。业务领导看着昨天的数据做今天的决策,这不扯淡吗?

我做过一个物流项目,要求每5分钟更新一次包裹位置。结果ETL任务跑一次要15分钟。数据还没跑完,快递都送到下一站了。后来我们优化了增量抽取策略,才把延迟压到2分钟以内。

时效性评估指标:
  • 数据产生到可用的时间差(延迟)
  • 批处理任务的完成时间窗口
  • 实时数据的最大容忍延迟
  • 数据过期后的处理策略(比如超过1小时的数据直接丢弃)

3.2 常见数据质量问题

上面讲了四个维度,下面咱们看看实际工作中最常见的坑。我列了个表,都是血泪教训。

问题类型 具体表现 影响
缺失值 字段为NULL、空字符串、占位符(如"未知") 统计结果偏差,模型训练失败
重复数据 同一记录出现多次,主键冲突 聚合计算翻倍,报表失真
异常值 超出合理范围的数据(如负数年龄) 拉偏平均值,影响分析结论
格式错误 日期格式不统一,电话号码含字母 解析失败,ETL任务报错
业务逻辑冲突 订单金额与明细合计不符 财务对账不平,审计通不过
数据漂移 同一指标在不同时间查询结果不同 业务决策失去依据

为什么会这样?我总结下来,根源无非三个:

  1. 上游系统不规范:业务系统设计时就没考虑数据质量
  2. 人为操作失误:手工录入、批量导入时出错
  3. 系统间集成问题:接口变更、字段映射错误

3.3 数据清洗策略

发现问题只是第一步,怎么清洗才是真功夫。下面是我常用的几种策略。

3.3.1 缺失值处理

遇到NULL值,不能一刀切。得看场景。

  • 删除:缺失比例很低(<5%),且该字段对分析不重要
  • 填充:用均值、中位数、众数填充。比如用户年龄缺失,可以用整体平均年龄
  • 预测填充:用机器学习模型预测缺失值。适合关键字段
  • 标记:保留NULL,但加一个"是否缺失"的标记字段
我的经验:金融风控场景,缺失值千万别随便填充。有时候"缺失"本身就是一种信号。比如用户故意不填收入,可能意味着什么?你懂的。

3.3.2 重复数据去重

去重不是简单的DISTINCT。你得先定义"重复"的标准。

-- 精确去重:所有字段完全一致
SELECT DISTINCT * FROM orders;

-- 业务去重:基于业务主键去重
WITH dedup AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY order_id 
      ORDER BY update_time DESC
    ) AS rn
  FROM orders
)
SELECT * FROM dedup WHERE rn = 1;

我建议用业务主键去重,保留最新的一条。比如订单号相同,取最后更新的那条记录。

3.3.3 异常值处理

异常值有两种:一种是明显错误(比如年龄200),一种是统计异常(比如交易金额突然放大100倍)。

  • 阈值截断:设定上下限,超出则截断或置为NULL
  • 分箱处理:将连续值离散化,比如年龄分为0-18、18-30、30-50、50+
  • IQR方法:用四分位距识别离群点
注意:异常值不一定是错误。比如双十一的订单量突然暴涨,那是正常业务波动。别把正常数据当异常给洗掉了。

3.3.4 格式标准化

格式问题,说白了就是统一规范。

-- 日期格式统一
SELECT 
  CASE 
    WHEN date_str LIKE '%/%' THEN TO_DATE(date_str, 'YYYY/MM/DD')
    WHEN date_str LIKE '%-%' THEN TO_DATE(date_str, 'YYYY-MM-DD')
    ELSE NULL
  END AS standardized_date
FROM raw_data;

-- 手机号清洗(去除非数字字符)
SELECT 
  REGEXP_REPLACE(phone, '[^0-9]', '') AS clean_phone
FROM users;

我习惯在ETL入口层就做格式标准化。越早做,后面越省心。

3.3.5 业务规则校验

这个最复杂,也最重要。你得懂业务才能做。

举个例子:订单金额 = 商品单价 × 数量 + 运费 - 优惠。如果这个等式不成立,数据就有问题。

-- 业务规则校验示例
SELECT order_id,
  CASE 
    WHEN ABS(total_amount - (unit_price * quantity + freight - discount)) > 0.01 
    THEN '金额不一致'
    ELSE '正常'
  END AS check_result
FROM orders;

我曾经遇到过一个案例:某电商的优惠券金额居然大于订单金额,导致退款时出现负数。这种问题,光靠数据清洗解决不了,得推动业务系统改逻辑。

3.4 数据质量的知识体系

下面这张图,是我自己总结的数据质量与清洗的知识框架。你照着这个思路走,基本不会跑偏。

数据质量与清洗知识体系 数据质量管理 完整性 准确性 一致性 时效性 常见数据质量问题 缺失值 重复数据 异常值 格式错误 数据清洗策略 缺失值处理 去重 异常值处理 格式标准化 目标:干净、可靠、可用的数据

3.5 我的几点建议

最后,分享几个实战中的心得。

  • 数据质量要前置:别等到数据进数仓了再洗。在源系统、在抽取阶段就做校验,成本最低。
  • 建立质量监控看板:每天自动跑质量检查,异常数据自动告警。我习惯用邮件+钉钉双通道通知。
  • 保留原始数据:清洗前一定要备份原始数据。万一洗错了,还能回滚。这个坑我踩过,不说了都是泪。
  • 清洗规则要文档化:每条清洗规则,谁定的、为什么这么定、什么时候改的,都得记清楚。不然半年后你自己都看不懂。
避坑指南:我曾经在一个项目中,为了追求数据"干净",把大量异常数据直接删除了。结果业务部门找上门来,说那些"异常"数据其实是新业务的测试数据。从那以后,我所有清洗操作都加了一个"数据质量标记字段",把原始值和清洗后的值都保留下来。这样出了问题,随时可以追溯。

数据质量这事儿,没有一劳永逸的解法。它是个持续改进的过程。你做得越久,遇到的坑越多,经验也就越丰富。嗯,今天就聊到这儿,希望对你有帮助。

公众号:蓝海资料掘金营,微信deep3321