写点什么

线上数据问题排查案例分享 - 因为 HMS 和底层 orc 文件中某字段的数据精度不一致造成的数据丢失问题

  • 2022-10-31
    湖北
  • 本文字数:2854 字

    阅读完需:约 9 分钟

线上数据问题排查案例分享-因为 HMS 和底层 orc 文件中某字段的数据精度不一致造成的数据丢失问题

大家好,我是明哥,本篇文章跟大家分享一次线上数据问题的排查案例,并总结下背后的技术背景和最佳实践,希望对大家有所帮助。

1. 避坑指南和最佳实践

先说下通过本案例总结的避坑指南和最佳实践。


  • hive 的元数据服务 hms 和表底层的 orc 文件中都存储了表的元数据信息,两者天然是割裂的,当两者信息不一致时,容易出现各种奇怪的数据问题;

  • 为避免潜在的数据问题,开发人员需要确保 hms 和 orc 文件中元数据信息的一致,为此应尽量避免更改 hive orc 表字段的数据类型(尤其需要避免对已存储了数据的 orc 表字段做数据类型不兼容的修改);

  • 为避免潜在的数据问题,使用同步工具如 datax 等直接同步数据到 orc 文件时,orc 文件也应该尽量使用对应表在 HMS 中定义的数据类型和数据精度来进行数据同步;

  • 为避免潜在的数据问题,使用 SQL 语句进行数据查询操作时,在数据类型不一致时,应尽量使用 CAST 进行显示转换而不依赖 HIVE SQL 的隐式转换机制;

2. 问题现象

某客户现场部分 HIVE ORC 表在各层的数据条数不一致,存在数据丢失问题。


比如对于 hive orc 表 hs_sr.sr_xxx/hs_ods.ods_xxx/hs_tmp.tmp_pxxx, 使用 count(1) 查询,发现 hs_sr 和 hs_ods 记录条数一致,但 hs_tmp 层则缺少了 400 条左右数据。


进一步查询发现,指定条件如 prod_code 查询某条数据时,在 hs_sr 层可以查到该条数据但在 hs_tmp 层查不到该条数据,而在 hs_ods 层查询该条数据时, 只要查询字段列表中包含 prod_scale 字段就会查不到该条数据,而查询字段列表不包含 prod_scale 字段就可以查询到该条数据。


备注:***本案例中,数据链路为使用 datax 从上游交易系统 oracle 采集到 hive 中的 hs_sr 层,然后使用 hive sql 对 hs_sr 层进行加工处理后写入到 hs_ods 层,再经过 hive sql 进一步加工处理后写到 hs_tmp 层。



3. 问题原因-概述

简单来讲,问题原因是 prod_scale 字段在 hive 表中的数据类型和数据精度跟 hive 表底层 orc 文件中的数据类型和数据精度不一致,当 orc 文件中部分记录 prod_scale 字段实际存储的值大于 hive 中定义的该字段的精度时,hive 查询该字段并写入到下游 ORC 表时会隐式转换为 NULL 值,而部分版本的 HIVE 在将 NULL 值写入 ORC 文件时有 BUG,会造成底层 ORC 文件中部分记录该字段不可读,所以后续 hive 再次在有问题的 ORC 文件中查询问题字段并插入最下游的 ORC 表时,下游表中就缺失了部分记录。。

4. 解决方案

解决方案按照思路不同分为两种,一种是业务侧的调整,一种是平台侧/工具侧的调整。

4.1 业务侧调整

业务侧调整,可以调整 hive 中相关表相关字段在 DDL 定义中的数据类型和数据精度,使之与上游交易系统 ORALCE 中相关字段的数据类型和数据精度一致,比如这里发现的 prod_scale 字段应从 decimal(15,4) 调整为 decimal(18,4);(查询上游交易系统 oracle 中的数据,发现确实有部分记录的 prod_scale 字段值比 decimal(15,4)精度更大,且业务确认这部分数据是正常数据,故应该调整 HIVE 中字段的数据类型和数据精度与上游一致);

4.2 平台侧/工具侧调整

本案例中使用了 datax 从上游 oralce 同步数据到 hive orc 表,故可以对 datax 同步作业进行调整:datax 同步数据时,数据类型和数据精度应该以目标 HIVE 表中定义的数据类型和数据精度为准,对于 decimal 字段也应该以目标 hive 表中的定义为准,而不是全部使用默认的最大精度 decimal(38,18),从而避免 orc 文件和 hms 中相关元数据信息的不一致,减少后续数据类型隐式转换等操作带来的潜在问题。(datax 同步作业调整后,在数据同步过程中,如果遇到上游 ORACLE 数据精度大于 HIVE 目标表的数据精度,同步作业会报错退出,从而能第一时间暴露数据问题确保数据质量,而不会将数据质量问题带到下游)。


备注:由于开源的 datax 并不支持 hive 的 decimal 数据类型,而金融行业对数据准确性普遍要求较高,故我司内部对 datax 做了增强,支持 hive 的 decimal 数据类型。**

5. 问题原因-技术细节

  • 本案例中数据链路如下:使用 datax 从上游交易系统 oracle 采集到 hive 中的 hs_sr 层,然后使用 hive sql 对 hs_sr 层进行加工处理后写入到 hs_ods 层,再经过 hive sql 进一步加工处理后写到 hs_tmp 层;

  • 本案例中,hive 中 hs_sr/hs-ods/hs_tmp 层相关表中关键字段 prod_scale 都被定义为了 decimal(15,4), 而上游 ORACLE 中该字段类型为 decimal(18,4);

  • orc 文件:采集上游 oracle 表数据并写入 hive orc 表时,对于 decimal 类型的字段,当前 datax 作业使用的都是 hive 默认的最大精度即 decimal(38,18),所以所有记录所有字段无论精度大小都能被同步到 ORC 文件中;

  • hs_sr 层表:但 HIVE 的 hs_sr 层表中该字段被定义为了更小精度 decimal(15,4),跟底层 orc 文件中的 decimal(38,18) 并不一致,所以 hive 查询该字段时就会隐式转换为目标类型 decimal(15,4),此时更大精度的值会被转换为 NULL 值进行处理,所以 hs_sr 层的表查询时不会缺少记录,但大精度的字段值会被显示为 NULL;

  • hs_ods 层表:在查询 hs_sr 层表数据再写入 hs_ods 层表时,由于上述隐式转换的原因,部分大精度字段值会被转换为 NULL 值进行处理,而部分版本的 HIVE 在将 NULL 值写入 ORC 文件时有 BUG,会造成底层 ORC 文件中部分记录该字段不可读,具体哪些记录该字段受到影响跟底层 orc 文件中对应的 stripe 中存储了哪些记录的该字段有关,所以 hs_ods 层表只要查询字段列表中包含 prod_scale 字段就会查不到该条数据,而查询字段列表不包含 prod_scale 字段就可以查询到该条数据,同时使用 count(1) 也会发现数据条数没有缺失;

  • hs_tmp 层表:后续查询 hs_ods 层表数据并写入 hs_tmp 层表时,由于 hs_ods 层表底层的 orc 文件中部分 stripe 有问题,所以当查询字段列表包含 prod_scale 字段时,对应 stripe 中的记录都会受到影响查询不到,最终插入 hs_tmp 层的数据也就缺失了这部分记录,使用 count(1) 也会发现数据条数有缺失,即最终出现了数据丢失问题;

6. 技术背景

  • ORC 文件是自描述格式,orc 和 hms 中都存储了表的元数据信息,所以二者天然是割裂的;

  • 当 hive 查询 ORC 表数据时,如果 orc 文件和 hms 中字段类型元数据信息不一致就会涉及到隐式转换;

  • HIVE 并不是 ANSI dialect compliant 的,即 HIVE 并不符合 ANSI SQL 标准,在处理无效数据时会返回 NULL 值而作业不会报错;

  • hive 中 decimal 类型的默认精度也即最大精度是 decimal(38,18), 当 decimal 类型的字段值在转换为更小精度比如 decimal(15,4) 时,较大精度的值会被转换为 NULL 值(隐式和显示转换都是如此);

  • 部分老版本的 hive 写 ORC 文件时在处理隐式转换的 NULL 值时有 BUG,会造成底层写入的 ORC 文件中的部分记录该字段不可读,但作业不会报错,具体哪些记录受到影响跟底层 orc 文件中对应 stripe 存储了哪些记录该字段有关;

  • 可以使用工具如 hive --orcfiledump xx 来验证表底层 orc 文件的完整性;


  1. 相关 JIRA


https://issues.apache.org/jira/browse/HIVE-13083



发布于: 刚刚阅读数: 4
用户头像

Keep Striving! 2018-04-25 加入

明哥,十四年 IT经验,六年大数据经验; 做过大数据集群的搭建运维,大数据应用系统的开发优化,也做过大数据平台的技术选型以及架构咨询; 目前聚焦于泛大数据生态,包括数据仓库/数据湖,云计算和人工智能。

评论

发布
暂无评论
线上数据问题排查案例分享-因为 HMS 和底层 orc 文件中某字段的数据精度不一致造成的数据丢失问题_hadoop_明哥的IT随笔_InfoQ写作社区