数据迁移问题排查
场景描述
公司要将数仓从 Hive 迁移到 ClickHouse,迁移后发现部分指标数据对不上。
迁移常见问题
| 问题 | 原因 | 排查方法 |
|---|---|---|
| 数据量不一致 | 迁移丢数 / 过滤条件差异 | COUNT 对比 |
| 数值不一致 | 类型精度丢失 / 空值处理差异 | SUM 对比 + 抽样检查 |
| 时区不一致 | 源和目标时区设置不同 | 检查同一条记录的时间字段 |
| 字符编码问题 | UTF-8 vs GBK | 检查中文/特殊字符 |
| 增量遗漏 | CDC 有延迟 | 检查最大 ID / 最大时间戳 |
数据校验步骤
1. 总量校验
-- 源端(Hive)
SELECT dt, COUNT(*) AS cnt, SUM(amount) AS total_amount
FROM hive_db.order_fact
WHERE dt = '2024-01-15'
GROUP BY dt;
-- 目标端(ClickHouse)
SELECT dt, COUNT(*) AS cnt, SUM(amount) AS total_amount
FROM ck_db.order_fact
WHERE dt = '2024-01-15'
GROUP BY dt;
-- 对比结果:cnt 和 total_amount 应完全一致
2. 抽样校验
-- 随机抽取 1000 条记录对比
SELECT order_id, user_id, amount, created_at
FROM hive_db.order_fact
WHERE dt = '2024-01-15'
ORDER BY RAND()
LIMIT 1000;
-- 在目标端逐条核对
3. 维度交叉校验
-- 按关键维度聚合对比
SELECT dt, channel, city,
COUNT(*) AS cnt,
SUM(amount) AS total_amount
FROM order_fact
WHERE dt = '2024-01-15'
GROUP BY dt, channel, city;
自动化校验脚本
import pandas as pd
def data_validation(source_df, target_df, pk_cols, check_cols):
"""数据迁移校验"""
report = {}
# 1. 行数对比
report['source_count'] = len(source_df)
report['target_count'] = len(target_df)
report['count_match'] = report['source_count'] == report['target_count']
# 2. 数值列聚合对比
for col in check_cols:
s_sum = source_df[col].sum()
t_sum = target_df[col].sum()
diff_pct = abs(s_sum - t_sum) / s_sum * 100 if s_sum != 0 else 0
report[f'{col}_diff_pct'] = f'{diff_pct:.4f}%'
# 3. 主键重叠检查
source_pk = set(source_df[pk_cols].apply(tuple, axis=1))
target_pk = set(target_df[pk_cols].apply(tuple, axis=1))
report['missing_in_target'] = len(source_pk - target_pk)
report['extra_in_target'] = len(target_pk - source_pk)
return report
常见面试问题
Q1: 数仓迁移如何做到零停机?
答案:
双写 + 灰度切换:
- 双写阶段:新旧数仓同时写入,保持一致
- 校验阶段:每日对比新旧数仓数据,确保一致
- 灰度切换:先切读流量(BI 报表),确认无误后再切全量
- 回退方案:切换后保留旧数仓 1-2 周,随时可回退
Q2: 迁移后数值有微小差异(0.01%)是否可接受?
答案:
需要分析差异原因:
- 浮点精度:Hive DOUBLE vs ClickHouse Float64,可能有精度丢失 → 可接受,但建议用 DECIMAL
- 空值处理:Hive 的 NULL + 10 = NULL vs ClickHouse 可能 = 10 → 不可接受,需统一
- 时区差异:跨天的订单归属日期不同 → 不可接受,需统一
结论:精度引起的微小差异可接受;逻辑差异不可接受。