
1. 这不是“测试流程图”而是一张能直接上手干活的路线图“数据测试全流程总结小白易上手”——看到这个标题我第一反应不是打开PPT画UML图而是立刻翻出自己三年前刚转行做数据质量保障时那本边角卷起、咖啡渍浸透的笔记本。里面密密麻麻记着第一次跑通SQL校验脚本却漏掉了NULL值处理导致线上报表凌晨两点崩掉第一次写数据血缘文档把ETL任务名当表名填进元数据系统被下游分析师追着问了三天还有一次因为没校验时间分区字段的格式一致性让整条离线链路连续两天产出空分区……这些不是“踩坑记录”是数据测试这件事最真实的入门门槛。所谓“全流程”绝不是从需求评审→测试设计→用例执行→缺陷提交→报告输出这种教科书式循环。真实世界里数据测试的起点往往是一封邮件“老板说下周要上线新用户分群模型数仓那边已经建好dwd_user_profile_v2你帮忙看看数据对不对。”——没有明确需求文档没有接口契约甚至没有字段注释。你的第一件事不是写用例而是蹲在Hive CLI里敲DESCRIBE FORMATTED dwd_user_profile_v2看清楚这张表到底是谁建的、最后更新时间是什么、分区字段叫什么、存储格式是不是ORC、是否启用压缩。这一步决定了你后续所有动作是事半功倍还是原地打转。“小白易上手”的核心从来不是降低技术深度而是把隐性经验显性化、把模糊判断标准化、把依赖直觉的操作变成可复现的步骤。比如“检查数据是否正确”老手会下意识关注三个维度完整性该有的记录有没有丢、一致性同一条业务逻辑在不同表里结果是否一致、准确性数值计算是否符合业务定义。而新手常卡在第一步连“该有的记录”指什么都说不清。所以这篇总结不讲抽象理论只拆解我在实际项目中每天都在做的动作怎么快速定位一张新表的核心字段、怎么用5分钟写出带断言的校验SQL、怎么一眼识别出ETL任务里的逻辑陷阱、怎么把开发甩过来的“数据没问题”这句话转化成可验证的证据链。它适合刚接手数据看板验收的BI同学也适合被临时拉来支援数仓交付的后端工程师更适合想从Excel核对转向系统化验证的数据运营——只要你需要确认“数据到底准不准”这篇就是你的第一份实操手册。2. 全流程不是线性流水线而是三层防御网的动态协同2.1 为什么必须放弃“测试阶段”的思维定式很多新人把数据测试理解为开发完成后的“质检环节”就像工厂流水线末端的抽检。但数据链路的特殊性在于上游一个字段类型变更比如VARCHAR(20) → VARCHAR(50)可能在下游引发连锁雪崩——聚合口径错位、JOIN失效、空值传播、甚至调度任务因内存溢出而失败。等你拿到最终宽表再开始测试问题早已渗透到多个层级。我见过最典型的案例某次营销活动数据看板异常排查发现根源是上游ODS层一张日志表的user_id字段从字符串类型悄悄改成了BIGINT而下游所有依赖该字段的JOIN操作都未做类型强转导致大量用户关联丢失。问题暴露在T3的报表上但根因发生在T-7的数仓模型迭代中。因此真正的“全流程”本质是覆盖数据生命周期的三层防御网第一层源头守门Source Guard在数据接入阶段就介入不等数据落库就验证。比如Kafka消息体JSON Schema是否与约定一致、日志采集埋点字段是否缺失、API返回数据结构是否发生breaking change。这一层的目标是“不让脏数据进门”。第二层链路免疫Pipeline Immunity在ETL加工过程中嵌入轻量级校验点。不是等整个任务跑完才检查结果而是在关键节点如清洗后、聚合前、维度关联后插入校验逻辑。例如在用户行为宽表生成后立即执行SELECT COUNT(*) FROM dwd_user_event WHERE event_time 2024-01-01若返回非零值说明时间分区逻辑有误立刻中断后续任务。第三层消费验证Consumer Validation面向最终使用场景的闭环验证。不只是查总数对不对更要模拟真实查询路径BI看板的SQL是否因字段别名变更而报错机器学习特征工程脚本读取的字段类型是否与训练时一致甚至包括下游API返回的JSON字段是否多出空格导致前端解析失败。这一层的目标是“确保数据能被正确使用”。这三层不是割裂的而是通过统一的元数据标记和自动化触发机制联动。比如在数据血缘系统中标记某张表为“高风险主维表”则所有上游变更自动触发其下游3层内的全链路回归校验又比如某次ETL任务在第二层校验中失败系统不仅告警还会自动回滚至前一稳定版本并通知相关方——这才是现代数据测试的基础设施底座。2.2 小白最容易忽略的“隐形流程”元数据驱动的测试资产沉淀新手常陷入一个误区每次接到新需求都从零开始写SQL、建临时表、手动比对。三个月后发现自己写了27个校验脚本但没人知道它们存在更没人复用。而资深从业者的第一动作永远是打开元数据管理平台搜索目标表名查看它的业务归属、更新频率、核心指标定义、历史校验规则、已知缺陷记录。这就是“全流程”中最具杠杆效应的一环测试资产的沉淀与复用。它包含三个硬性动作字段级业务语义标注不只是记录“user_id STRING”而是补充“【主键】全局唯一用户标识来源于登录系统长度16位十六进制字符串空值率0.01%”。这种标注直接决定校验策略主键字段必须做NOT NULL COUNT(DISTINCT) COUNT(*)校验空值率阈值则用于设置告警灵敏度。校验规则模板化封装把高频校验逻辑封装成可配置的模板。例如“金额类字段校验模板”包含非负性检查WHERE amount 0精度合规性WHERE LENGTH(SUBSTRING_INDEX(amount, ., -1)) 2与上游订单表的SUM一致性比对使用时只需填写表名、字段名、容忍误差百分比自动生成完整SQL。缺陷根因反哺模型治理每次发现数据问题必须登记到数据治理平台强制关联问题表及字段触发场景如“双11大促期间订单状态流转异常”根本原因如“支付成功事件与订单创建事件时间戳精度不一致导致状态判定延迟”改进建议如“在ODS层增加事件时间标准化函数”这些记录会自动推送至数仓模型负责人推动源头治理。我团队曾统计引入这套元数据驱动机制后新表的首次校验耗时从平均8小时降至1.5小时重复性问题复发率下降63%。因为新人不再需要重新发明轮子而是站在前人标注好的“路标”上快速前进——这才是“小白易上手”的底层支撑。3. 核心环节拆解从接到需求到交付验证的7个关键动作3.1 动作15分钟锁定“这张表到底在干啥”新手面对一张陌生表常直接SELECT * FROM table LIMIT 10然后对着满屏字段发呆。真正高效的起点是用结构化提问法快速建立认知框架Q1这张表服务于哪个业务域查元数据系统中的“业务分类”标签或直接问对接的产品经理“这个表主要支撑哪类决策比如是用于实时监控、月度复盘还是算法训练”——答案决定校验粒度实时监控需秒级延迟校验月度复盘可接受T1算法训练则要求字段分布稳定性。Q2它的数据新鲜度要求是什么看表的分区字段命名如dt STRING通常代表天级hour STRING代表小时级和最近分区数据时间戳。曾有个案例业务方声称“需要实时用户画像”但表实际按天分区最新数据是昨天的——这直接否定了实时性需求避免后续做无用功。Q3谁是这张表的“主人”元数据中“责任人”字段常为空此时要查Git仓库中建表DDL的提交记录或追溯调度任务的Owner。找到真人后第一句话不是“数据对不对”而是“请问这张表的核心业务逻辑是怎样的比如user_status字段0/1/2分别代表什么状态是否有中间态”——很多问题源于业务语义理解偏差。实操技巧我习惯用Excel快速整理三列——字段名、业务含义来自文档或访谈、校验重点如“order_amount需检查非负性、小数位数、与支付流水表SUM比对”。这张表就是后续所有动作的导航图。3.2 动作2用“三明治SQL”法写校验脚本附模板所谓“三明治SQL”是指将校验逻辑嵌套在标准查询结构中形如-- 【顶层】业务口径定义 WITH biz_logic AS ( SELECT user_id, SUM(order_amount) AS total_paid, COUNT(DISTINCT order_id) AS order_cnt FROM dwd_order_detail WHERE dt 20240520 AND status paid -- 业务定义的“已支付”状态 GROUP BY user_id ), -- 【中层】数据质量断言 quality_check AS ( SELECT total_paid_non_negative AS check_name, COUNT(*) AS failed_cnt FROM biz_logic WHERE total_paid 0 UNION ALL SELECT order_cnt_positive AS check_name, COUNT(*) AS failed_cnt FROM biz_logic WHERE order_cnt 0 ), -- 【底层】结果汇总与告警 final_result AS ( SELECT check_name, failed_cnt, CASE WHEN failed_cnt 0 THEN ALERT ELSE PASS END AS status FROM quality_check ) SELECT * FROM final_result;这个结构的优势在于可读性强业务逻辑biz_logic、质量规则quality_check、结果呈现final_result物理隔离修改任一层不影响其他层可复用性高替换biz_logic中的表名和条件即可迁移至其他表调试友好逐层注释运行快速定位问题环节如发现biz_logic结果为空则问题在数据源或过滤条件。新手常见错误把所有逻辑写在一个SELECT里导致无法分段验证。我建议初期强制使用此模板哪怕只写一条校验规则也要保持三层结构——这是培养工程化思维的最小实践单元。3.3 动作3识别ETL任务中的“逻辑暗礁”数据测试最大的挑战往往不在SQL本身而在ETL任务的隐含逻辑。以下是我在生产环境中高频遇到的5类“暗礁”附识别方法暗礁类型典型表现快速识别法应对策略时间窗口漂移分区数据量突增/突减但业务无明显变化对比近7天同一分区的记录数趋势若波动30%且无业务事件检查任务调度时间是否与业务高峰重叠导致延迟在任务开头添加SELECT MAX(event_time) FROM source_table WHERE dt ${bdp.system.bizdate}校验数据时效性空值传染链A表JOIN B表后B表某字段为空导致A表关联字段全部为空执行SELECT COUNT(*) FROM A LEFT JOIN B ON A.idB.id WHERE B.field IS NULL若结果0说明存在空值关联风险强制使用COALESCE(B.field, UNKNOWN)并在元数据中标记该字段为“允许空值”精度丢失陷阱计算结果小数位数异常如0.9999999999999999对数值字段执行SELECT ROUND(field, 2), field FROM table LIMIT 10观察原始值与四舍五入值差异在ETL中统一使用DECIMAL类型避免FLOAT/DOUBLE中间计算去重逻辑冲突同一业务实体在不同来源表中ID不一致导致去重后丢失记录抽样检查SELECT id, COUNT(*) FROM table GROUP BY id HAVING COUNT(*) 1若存在说明ID生成规则不唯一推动上游统一分发ID或在DWD层建立ID映射表分区裁剪失效任务执行时间远超预期日志显示扫描全表查看执行计划确认WHERE dt20240520是否生效若无效检查分区字段名是否拼写错误如dayvsdt在建表DDL中强制指定PARTITIONED BY (dt STRING)禁止使用别名关键心得不要迷信任务名称。曾有个任务叫dwd_user_profile_full我以为是全量快照结果发现是增量合并——进去看代码才发现用了INSERT OVERWRITE但WHERE条件写成了WHERE dt ${bdp.system.bizdate}实际每天覆盖近30天数据。所以我的铁律是任何ETL任务必看源码不看描述。3.4 动作4构建“最小可行验证集”MVV新手常陷入“全面覆盖”陷阱试图校验所有字段、所有组合。但数据测试的本质是风险导向——优先验证对业务影响最大的部分。我采用“最小可行验证集MVV”方法仅用3步锁定核心验证点Step 1锚定1个核心业务指标例如电商场景中“当日GMV”是生死线指标。围绕它逆向追溯GMV Σ(订单金额)订单金额来源dwd_order_detail.order_amount订单状态过滤status IN (paid, shipped)时间范围event_time 2024-05-20 00:00:00Step 2识别3个关键约束条件基于该指标提炼不可妥协的硬性约束约束1order_amount必须≥0业务逻辑约束2status枚举值只能是[created,paid,shipped,closed]数据字典约束3event_time必须在当日0点至24点之间时间有效性Step 3设计1组穿透式验证SQL将上述要素整合为单条可执行SQL一次验证全部约束SELECT COUNT(*) AS total_records, SUM(CASE WHEN order_amount 0 THEN 1 ELSE 0 END) AS negative_amount_cnt, SUM(CASE WHEN status NOT IN (created,paid,shipped,closed) THEN 1 ELSE 0 END) AS invalid_status_cnt, SUM(CASE WHEN event_time 2024-05-20 00:00:00 OR event_time 2024-05-21 00:00:00 THEN 1 ELSE 0 END) AS out_of_range_cnt FROM dwd_order_detail WHERE dt 20240520;只要这条SQL返回的四个数值中后三个均为0即可认为该表在核心业务场景下可信。MVV的价值在于用20%的验证工作覆盖80%的关键风险。等核心链路稳定后再逐步扩展至次要指标。3.5 动作5用“血缘快照”替代人工比对当业务方说“新旧版本数据不一致”新手第一反应是导出两份CSV用Excel比对。这在千万级数据下完全不可行。我的替代方案是基于数据血缘的差异快照。操作流程在血缘平台中输入新旧两个版本的表名如dwd_user_profile_v1vsdwd_user_profile_v2平台自动生成“血缘差异报告”包含字段增删列表v2新增last_login_device_type删除old_user_tag加工逻辑变更点v2中user_level计算由CASE WHEN active_days30 THEN VIP...改为调用UDFget_user_level()依赖上游变更v2新增依赖ods_user_behavior_log而v1仅依赖ods_user_register针对差异点编写靶向校验对新增字段检查空值率、分布合理性如last_login_device_type应包含ios,android,web对逻辑变更构造边界用例验证UDF结果如传入active_days31检查返回是否为VIP对新增上游依赖验证JOIN键匹配度SELECT COUNT(*) FROM v2 t1 LEFT JOIN ods_user_behavior_log t2 ON t1.user_idt2.user_id WHERE t2.user_id IS NULL。这种方法将“数据是否一致”的模糊问题转化为“差异点是否符合预期”的精确验证效率提升10倍以上。血缘工具不是锦上添花而是数据测试的基础设施。3.6 动作6把“口头承诺”变成可执行的契约开发常说“这个字段保证不为空”、“这个指标绝对准确”。但口头承诺无法审计。我的做法是用Schema文件固化契约。以JSON Schema为例为dwd_user_profile表定义{ type: object, properties: { user_id: { type: string, minLength: 16, maxLength: 16, pattern: ^[0-9a-f]{16}$ }, total_paid: { type: number, multipleOf: 0.01, minimum: 0 } }, required: [user_id, total_paid] }然后用开源工具jsonschema进行自动化校验# 安装校验器 pip install jsonschema # 生成样本数据从表中抽样1000条 hive -e SELECT to_json(struct(*)) FROM dwd_user_profile LIMIT 1000 sample.json # 执行校验 python -m jsonschema -i sample.json schema.json若校验失败会精准定位到第几行第几个字段违反哪条规则。这种契约化管理让“数据质量”从主观评价变为客观事实。新人只需学会写Schema和运行命令就能获得专业级保障。3.7 动作7交付不是交报告而是交“信任凭证”测试报告常沦为形式主义罗列一堆PASS/FAIL业务方看不懂开发不认账。我的交付物是信任凭证包包含三件套可视化健康看板用Grafana搭建实时看板展示核心表的每日校验通过率折线图最近7天TOP5失败校验项柱状图关键指标波动预警如GMV环比变化±15%标红业务方无需看SQL一眼可知数据健康度。可追溯的证据链每次校验失败自动生成Markdown报告包含失败时间、涉及表、校验规则原始数据截图如SELECT * FROM table WHERE condition LIMIT 5修复前后对比修复后再次执行截图证明通过根因分析结论链接到Jira缺陷单这份报告可直接作为上线审批附件。自助式验证入口为业务方提供简易Web界面输入日期、选择校验项如“检查昨日订单金额非负性”一键执行并返回结果。降低他们的验证门槛也减少重复咨询。交付的本质是让数据使用者建立“我随时可以验证”的信心。当业务方自己点开链接就能确认数据可用测试工作才算真正闭环。4. 常见问题与实战排障指南附真实故障复盘4.1 问题1校验SQL总超时但表数据量并不大现象对一张仅500万行的表执行COUNT(DISTINCT user_id)Hive任务运行2小时仍无结果YARN日志显示Reducer卡在Shuffle阶段。排查路径先执行EXPLAIN EXTENDED SELECT COUNT(DISTINCT user_id) FROM table查看执行计划发现Distinct操作被推到Reduce阶段且user_id字段存在大量重复值倾斜检查user_id分布SELECT user_id, COUNT(*) c FROM table GROUP BY user_id ORDER BY c DESC LIMIT 10发现前10个user_id占总量70%根本原因user_id中混入测试账号如test_123导致数据倾斜。解决方案短期改用两阶段去重SELECT COUNT(*) FROM ( SELECT DISTINCT user_id FROM table DISTRIBUTE BY user_id SORT BY user_id ) t;长期在ODS层增加测试数据过滤规则元数据中标记user_id为“生产环境唯一标识”禁止测试值流入。提示数据倾斜是性能杀手但根源常在数据质量。不要只优化SQL先解决脏数据。4.2 问题2上下游表JOIN结果为空但各自都有数据现象dwd_order与dwd_user通过user_id关联单独查两张表均有数据但LEFT JOIN后dwd_user字段全为NULL。排查路径检查字段类型DESCRIBE dwd_ordervsDESCRIBE dwd_user发现dwd_order.user_id为STRINGdwd_user.user_id为BIGINT验证隐式转换SELECT 12345 12345返回TRUEHive默认转换但SELECT abc123 12345返回NULL抽样检查dwd_order.user_idSELECT user_id FROM dwd_order LIMIT 10发现存在U_12345这类带前缀的字符串根本原因上游系统变更user_id格式从纯数字升级为带业务前缀的字符串但下游未同步调整。解决方案立即修复在JOIN条件中显式转换CAST(dwd_order.user_id AS BIGINT)但需处理非法字符串根治方案推动上游发布新版本user_id规范并在元数据中强制要求字段类型一致性。注意类型不匹配是JOIN失效的头号原因务必在建表DDL中明确声明禁止依赖隐式转换。4.3 问题3校验通过但业务方反馈数据“看着不对”现象所有自动化校验均PASS但业务方指出“新用户占比突然从15%降到2%”不符合常识。排查路径不信校验结果直接查原始数据SELECT COUNT(*) FROM dwd_user WHERE register_time 2024-05-20 AND dt20240520发现结果为0但业务方说当天有10万注册检查分区逻辑dwd_user表按register_date分区但ETL任务中写入条件为WHERE dt ${bdp.system.bizdate}而dt字段实际存储的是process_date加工日期非注册日期根本原因分区字段语义与业务理解错位dt20240520实际对应的是5月19日注册的用户因T1加工。解决方案紧急修改任务按register_date分区并重建历史分区长效在元数据中为每个分区字段添加“业务含义”注释如dt: 数据加工日期非业务发生日期预防所有分区字段必须通过SELECT MIN(dt), MAX(dt) FROM table验证其业务合理性。实操心得当业务直觉与系统结果冲突时永远相信业务直觉。系统是人写的直觉是经验沉淀后者往往是更早的预警信号。4.4 问题4自动化校验天天报警团队习以为常现象告警群每天刷屏“dwd_order_detail校验失败”但无人处理最终演变为“狼来了”。根因分析校验规则过于宽松amount 0告警阈值设为100条但实际每天有50条测试订单缺乏分级机制严重问题如主键重复与轻微问题如空值率略超阈值混在同一告警通道无闭环跟踪告警发出后未关联Jira单也无负责人认领。重构方案三级告警体系P0阻断上线主键重复、核心字段全空、数据量归零P1需2小时内响应金额负值、状态非法、时间越界P2可批量处理空值率超阈值、分布偏移告警收敛同一P0问题24小时内重复告警只发1次附带历史趋势图自动创建工单P0/P1告警触发时自动创建Jira单分配给表Owner并设置SLAP02小时响应4小时解决。经验教训告警不是越多越好而是越精准越有效。把工程师从告警疲劳中解放出来才能聚焦真问题。4.5 问题5测试环境数据与生产环境不一致导致验证失效现象在测试环境校验通过的SQL在生产环境执行时报错Column not found。深度排查对比测试/生产环境的表结构DESCRIBE FORMATTED table发现生产环境多了etl_version STRING字段检查建表语句测试环境用CREATE TABLE AS SELECT生产环境用CREATE TABLE LIKE后者继承了源表所有字段根本原因测试环境未同步生产环境的模型变更且缺乏跨环境Schema一致性校验。落地措施建立“环境一致性检查”任务每日自动比对测试/生产环境同名表的字段列表、类型、注释差异项自动创建待办所有DDL变更必须走GitOps流程测试环境部署后自动触发一致性校验新人入职第一课DESCRIBE不是可选动作是每次执行SQL前的必做步骤。血泪提醒永远不要假设环境一致。生产环境的每一次变更都是对测试可靠性的考验。5. 工具链精简清单够用、免费、零学习成本5.1 不需要下载安装的“开箱即用”工具很多教程推荐一堆工具但小白最需要的是“今天装明天就能用”。我只推荐以下3个真正零门槛的SQL在线校验器https://sqlformat.org/粘贴你的校验SQL一键美化格式、检测语法错误、高亮关键词。避免因缩进混乱或括号缺失导致执行失败。我每天用它检查SQL可读性尤其当多人协作时统一格式能减少50%的沟通成本。正则表达式测试站https://regex101.com/验证字段格式规则如^[0-9a-f]{16}$是否匹配user_id。左侧输入样本数据右侧实时显示匹配结果和分组比在Hive里反复试错高效10倍。新手学正则这里就是最佳沙盒。JSON Schema验证器https://jsonschemalint.com/把Schema定义和样本数据粘贴进去立即返回验证结果。不用装Python环境不用写代码适合快速验证契约有效性。我把它设为浏览器收藏夹第一项。5.2 必装的本地小工具5分钟搞定VS Code SQLTools插件免费、轻量、支持Hive/Spark SQL语法高亮和智能提示。配置连接信息后直接在编辑器里执行SQL结果以表格形式展示比命令行友好太多。关键是——它支持保存SQL片段为代码片段Snippets比如我把“三明治SQL模板”存为sqldq输入sqldq回车就自动展开省去重复敲代码的时间。DBeaver社区版开源数据库客户端支持同时连接Hive、MySQL、PostgreSQL。最大优势是元数据浏览树双击表名自动展开字段列表、分区信息、建表语句比查文档快10倍。右键字段还能直接生成SELECT COUNT(*) WHERE field IS NULL这样的常用校验SQL。DataGrip教育版免费JetBrains出品对SQL重构能力极强。比如你想把WHERE dt20240520批量替换成WHERE dt${bizdate}它能智能识别所有上下文避免误替换字符串字面量。对于复杂SQL的维护这是生产力神器。实操建议不要贪多。先装VS CodeSQLTools用熟后再加DBeaver。工具的价值不在于功能多而在于每天节省的10分钟。5.3 自动化脚本3个Python小工具附源码所有脚本均基于Python3.6无需额外依赖复制即用工具1分区健康检查器#!/usr/bin/env python3 # partition_health.py import subprocess import sys def check_partition(table, date): cmd fhive -e \SELECT COUNT(*) FROM {table} WHERE dt{date}\ result subprocess.run(cmd, shellTrue, capture_outputTrue, textTrue) count int(result.stdout.strip()) if count 0: print(f⚠️ 警告{table} 在 {date} 分区无数据) else: print(f✅ {table} 在 {date} 分区有 {count} 条记录) if __name__ __main__: if len(sys.argv) ! 3: print(用法python partition_health.py 表名 日期) sys.exit(1) check_partition(sys.argv[1], sys.argv[2])用法python partition_health.py dwd_user_profile 202405205秒获知分区是否为空。工具2字段空值率扫描器#!/usr/bin/env python3 # null_ratio.py import subprocess import sys def scan_nulls(table, fields): for field in fields.split(,): field field.strip() cmd fhive -e \SELECT COUNT(*) as total, SUM(CASE WHEN {field} IS NULL THEN 1 ELSE 0 END) as null_cnt FROM {table}\ result subprocess.run(cmd, shellTrue, capture_outputTrue, textTrue) lines result.stdout.strip().split(\n) if len(lines) 2: total, null_cnt map(int, lines[1].split(\t)) ratio null_cnt / total * 100 if total 0 else 0 print(f{field}: {ratio:.2f}% 空值率) if __name__ __main__: if len(sys.argv) ! 3: print(用法python null_ratio.py 表名 字段列表逗号分隔) sys.exit(1) scan_nulls(sys.argv[1], sys.argv[2])用法python null_ratio.py dwd_order_detail user_id,order_amount,status批量扫描关键字段空值。工具3血缘关系生成器文本版#!/usr/bin/env python3 # lineage_text.py # 输入建表SQL输出文本版血缘关系 import re import sys def extract_lineage(sql): # 提取FROM和JOIN的表名 tables re.findall(r(?:FROM|JOIN)\s([^\s\(\)]), sql, re.IGNORECASE) # 提取INSERT INTO目标表 target re.search(rINSERT\sINTO\s([^\s\(\)]), sql, re.IGNORECASE) if target: print(f目标表: {target.group(1)}) print(上游依赖:) for t in set(tables): print(f ← {t}) if __name__ __main__: if len(sys.argv) ! 2: print(用法python lineage_text.py 建表SQL) sys.exit(1) extract_lineage(sys.argv[1])