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

简介: 线上数据问题排查案例分享-因为 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

image.png

相关文章
|
1天前
|
关系型数据库 MySQL API
Flink CDC产品常见问题之读取不到或读取不全消息如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
|
1天前
|
NoSQL 关系型数据库 Redis
DMS问题之归档后数据量和大小没变化如何解决
DMS(Data Management Service)是阿里云提供的一站式数据管理服务,支持数据开发、维护、治理等多种功能;本合集着重于介绍DMS的功能特点、操作流程和最佳实践,帮助用户高效进行数据管理和维护。
54 6
|
1天前
|
SQL 分布式计算 DataWorks
实时数仓 Hologres产品使用合集之在主键重复写入时无法保证保留最后一条记录如何解决
实时数仓Hologres是阿里云推出的一款高性能、实时分析的数据库服务,专为大数据分析和复杂查询场景设计。使用Hologres,企业能够打破传统数据仓库的延迟瓶颈,实现数据到决策的无缝衔接,加速业务创新和响应速度。以下是Hologres产品的一些典型使用场景合集。
16 0
|
1天前
|
分布式计算 DataWorks 大数据
MaxCompute产品使用合集之数据传输完成后发现了脏数据字段如何解决
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
1天前
|
SQL DataWorks 关系型数据库
DataWork数据处理问题之提示不存在如何解决
DataWork数据处理是指使用DataWorks平台进行数据开发、数据处理和数据治理的活动;本合集将涵盖DataWork数据处理的工作流程、工具使用和问题排查,帮助用户提高数据处理的效率和质量。
41 0
|
数据采集 分布式计算 监控
网站流量日志分析—数据入库—含义和 ETL 本质解释|学习笔记
快速学习网站流量日志分析—数据入库—含义和 ETL 本质解释
376 0
网站流量日志分析—数据入库—含义和 ETL 本质解释|学习笔记
|
SQL 算法 Java
百万级别数据Excel导出优化
这篇文章不是标题党,下文会通过一个仿真例子分析如何优化百万级别数据Excel导出。
766 0
百万级别数据Excel导出优化
|
SQL 监控 Java
SLS新增单位转换函数——消除数据转换烦恼
在日常工作中,经常会遇到数据单位或时间单位不一致的情况,当处理或分析此类数据时,往往费事费力,非常麻烦。 现在,SLS新增了单位转换函数,可以实现在不同单位之间轻松地进行转换、统一单位、格式化为可读文本,为用户减少不必要的数据转换工作,提升分析效率。
517 0
|
存储 缓存 分布式计算
数据湖实操讲解【JindoFS 缓存加速】第十四讲:指定表和分区来预先缓存,查询分析更高效
数据湖 JindoFS+OSS 实操干货 36讲 每周二16点准时直播! 扫文章底部二维码入钉群,线上准时观看~ Github链接: https://github.com/aliyun/alibabacloud-jindofs
数据湖实操讲解【JindoFS 缓存加速】第十四讲:指定表和分区来预先缓存,查询分析更高效
|
存储 运维 算法
CPU静默数据错误:存储系统数据不丢不错的设计思考
对于数据存储系统来说,保障数据不丢不错是底线,也是数据存储系统最难的部分。据统计,丢失数据中心10天的企业,93%会在1年内破产。那么如果想要做到数据不丢不错,我们可以采取怎样的措施呢?
CPU静默数据错误:存储系统数据不丢不错的设计思考
http://www.vxiaotou.com