3. 数据质量维度与治理指标设计
数据质量维度不是抽象口号,而是把“数据好不好用”拆成可定义、可计算、可追责的六个观察角度。在Databricks中,这六个维度最终都要落到三件东西上:一张表或一个字段、一条可执行的SQL或PySpark断言、一个随时间变化的指标值。只有同时具备这三者,维度才真正可治理。下面逐一说明每个维度在Databricks中的定义方式、典型度量表达式,以及结果如何判读。
完整性:该有的值不能缺
完整性衡量的是“应存在的数据是否真的存在”,通常分两个层次:行级完整性(应到达的记录是否到达)和列级完整性(关键字段是否为空)。在Databricks中,列级完整性最直接的度量是空值率:
SELECT
COUNT(*) AS total_rows,
SUM(CASE WHEN customer_id IS NULL THEN 1 ELSE 0 END) AS null_cnt,
ROUND(SUM(CASE WHEN customer_id IS NULL THEN 1 ELSE 0 END) / COUNT(*), 4) AS null_rate
FROM prod.silver.orders;
假设某日 total_rows = 1,000,000,null_cnt = 2,500,则 null_rate = 0.25%。若治理阈值设定为“关键字段空值率 ≤ 0.1%”,则该指标未达标,应触发告警。行级完整性则常用“应到 vs 实到”对比,例如上游订单系统当日应产生 100 万条,Delta表实际写入 98.7 万条,行级完整率 = 98.7%。注意:完整性阈值必须按字段分级,主键、金额、时间字段通常要求 0 空值,而备注类字段可放宽。
准确性:值与真实世界是否一致
准确性最难直接度量,因为“真实值”往往不在库内。Databricks中常用三种可操作方式:参照比对(与权威源对账)、业务规则校验(值域、格式、勾稽关系)、统计异常检测(分布偏移)。例如订单金额应等于明细金额之和,可用勾稽规则度量:
SELECT COUNT(*) AS mismatch_cnt
FROM prod.silver.orders o
JOIN (
SELECT order_id, SUM(amount) AS detail_sum
FROM prod.silver.order_items GROUP BY order_id
) d ON o.order_id = d.order_id
WHERE ABS(o.total_amount - d.detail_sum) > 0.01;
若 mismatch_cnt = 37,总订单 100 万,则准确率 = 1 − 37/1,000,000 = 99.9963%。准确性指标通常以“违规记录数 / 总记录数”表达,并保留样本明细供人工复核。在Databricks中可结合 expectations(Lakeflow Declarative Pipelines 的期望)在写入时直接拦截或标记违规行。
一致性:跨表、跨系统是否说得通
一致性关注同一事实在不同位置是否一致,包括跨表一致性(订单表与客户表的外键匹配)、跨系统一致性(Delta表与上游Kafka/数据库对账)、格式一致性(日期、编码、币种统一)。典型度量是外键失配率:
SELECT COUNT(*) AS orphan_cnt
FROM prod.silver.orders o
LEFT JOIN prod.silver.customers c ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL;
若 orphan_cnt = 120,则外键一致率 = 1 − 120/1,000,000 = 99.988%。一致性还常表现为“同一指标两个口径对不上”,例如财务口径GMV与业务口径GMV差异超过 0.5% 即视为不一致。治理上应把口径定义写入Unity Catalog的列注释或指标视图,避免各写各的SQL。
及时性:数据是否在需要时可用
及时性衡量数据从产生到可用的延迟,以及是否在SLA内完成。Databricks中可用Delta表历史(DESCRIBE HISTORY)或审计日志提取写入时间,计算数据新鲜度和SLA达成率:
SELECT
MAX(_commit_timestamp) AS last_commit,
TIMESTAMPDIFF(MINUTE, MAX(_commit_timestamp), CURRENT_TIMESTAMP()) AS lag_minutes
FROM prod.silver.orders;
假设SLA要求“每日 07:00 前完成T+1数据就绪”,实际最近提交时间为 07:42,则当日延迟 42 分钟,SLA未达成。及时性指标应记录延迟分钟数和近30天SLA达成率,例如 30 天中 28 天按时,达成率 93.3%。注意区分“数据产生时间”“入湖时间”“加工完成时间”三个时间戳,否则延迟会被低估。
唯一性:同一实体是否只出现一次
唯一性针对主键或业务键,度量重复记录的比例。在Delta表中可用窗口函数或 GROUP BY ... HAVING COUNT(*) > 1 检测:
SELECT COUNT(*) AS dup_keys FROM (
SELECT order_id FROM prod.silver.orders
GROUP BY order_id HAVING COUNT(*) > 1
);
若 dup_keys = 8,唯一率 = 1 − 8/1,000,000 = 99.9992%。唯一性还常与幂等写入相关:使用 MERGE INTO 按主键更新可避免重复累积。若重复率突然上升,往往意味着上游重跑或流式任务重复消费,应结合 _commit_version 排查。
有效性:值是否符合既定格式与规则
有效性检查值是否落在允许的集合、格式或范围内,例如邮箱格式、枚举值、日期范围、金额非负。Databricks中可用正则和范围条件度量:
SELECT
SUM(CASE WHEN email NOT RLIKE '^[^@]+@[^@]+\\.[^@]+$' THEN 1 ELSE 0 END) AS bad_email,
SUM(CASE WHEN status NOT IN ('NEW','PAID','SHIPPED','CLOSED') THEN 1 ELSE 0 END) AS bad_status
FROM prod.silver.orders;
若 bad_email = 300、bad_status = 15,则有效率分别为 99.97% 和 99.9985%。有效性规则应集中维护,例如放入Unity Catalog的约束或质量规则表,避免散落在各任务中。
把六个维度组织成可运行的治理指标
六个维度单独看并不难,难的是让它们在同一套机制里持续运行。推荐在Databricks中采用“规则表 + 调度任务 + 指标表 + 告警”的结构:把每个维度的检查SQL、阈值、责任人和告警级别登记到一张质量规则表(例如 governance.dq_rules),由Databricks Workflows按日调度执行,结果写入 governance.dq_metrics,字段至少包含 rule_id、table_name、dimension、metric_value、threshold、status、run_time。这样每个维度都有历史趋势,可以回答“上周完整性为什么掉了”这类问题。
阈值设定要避免“一刀切”。建议按字段重要度分级:主键、金额、时间字段用严格阈值(如空值率 0、唯一率 100%),一般属性字段用宽松阈值(如空值率 ≤ 5%)。同时区分阻断型与告警型规则:阻断型在写入时用期望直接拒绝,告警型只记录并通知。下面是一份可直接参考的规则登记示例:
| 维度 | 检查对象 | 度量表达式(示例) | 阈值 | 级别 |
|---|---|---|---|---|
| 完整性 | orders.customer_id | null_rate | ≤ 0.1% | 告警 |
| 准确性 | orders.total_amount | 勾稽违规率 | ≤ 0.01% | 阻断 |
| 一致性 | orders.customer_id → customers | 外键失配率 | ≤ 0.05% | 告警 |
| 及时性 | silver.orders 日批 | 完成延迟分钟 | ≤ 0 min(07:00前) | 告警 |
| 唯一性 | orders.order_id | 重复主键数 | = 0 | 阻断 |
| 有效性 | orders.status | 枚举违规率 | ≤ 0.01% | 告警 |
dq.null_rate(table, column)、dq.dup_key_rate(table, key),由规则表驱动调用,避免为每张表重复写SQL。指标结果建议同时写入Delta表并暴露为Databricks SQL Dashboard,让业务方直接看到六个维度的趋势。最后要强调:六个维度不是并列孤立的。完整性差会拉低准确性(空值参与计算导致偏差),唯一性差会破坏一致性(同一实体两条记录对不上),及时性差会让准确性失去意义(过期数据再准也没用)。因此在Databricks中设计治理指标时,应把六维度放在同一张指标宽表里按 table_name + run_date 对齐,观察它们之间的联动,而不是各自为政。这样,数据质量才从“检查项”变成“可运营的治理体系”。