[hive]外部分区表结构变更后查询为空问题解决

0X00 前提

本意是想见想记录以前遇到过的问题,由此引申出一些思考,关于目前hadoop等大数据生态,或多或少都会存在一些问题,重要是我们认清现实之后,热爱我们的选择。
关于技术上的成长,除了下文所说的要保持谦逊外,还在于积累和思考。
问题解决是怎样的不重要的,重要的是自己的总结,我也是想赶紧把这些记录下来以免以后忘了可惜,毕竟这个小问题也是两年前遇到过的,今日想起,顺手写下来。

数仓技术选型:hive+sqoop1.4.4
场景:数仓中ods增量表由于上游db表变更缘故,需要对应地增加两个字段,一般使用alter table table_name add columns(column_name type comment '');的方式来直接在hive中增加字段。但由于上下游之间信息传达、沟通不到位,导致在上游db的源表已经增加表字段数天后,数仓相关部门才收到通知,故数仓的变更除了对表修改之外,还需要对历史数据的刷新补位。
问题:新增字段后需要对增量表的历史分区进行数据刷新。使用sqoop同步数据到hive中覆盖增量表的分区,增量表为天分区外部表。在检验历史数据同步情况的时候,发现新增字段的数据显示为空。即外部分区表新增字段刷新历史分区数据后查询为空。

0X01 过程

分析:

  1. 通过对比,新增字段后同步产生的分区里面,数据能够正常查询,但问题出现在历史分区的查询。
  2. 由于是外部表,我们可以在hive中通过dfs -fs -cat的方式直接查看表数据文件(sqoop在map之后生成的hdfs文件),发现文件中最后两列(新增列,此处以txt格式文件为例)是有数据的。由此可知问题在于查询时对应列无法加载/被识别,而非同步有问题
  3. 通过调通sqoop来试验,发现将同步到的数据文件放到指定的其他hdfs路径下,并通过ALTER TABLE table_name ADD PARTITION (partCol = 'value1') location 'loc1'; 方式新增分区,发现数据能够正常查询。如果将历史分区的路径作为新分区的数据文件查询路径,也即新分区和某个历史分区共用同一个数据路径下的数据文件时,通过指定分区名的方式分别查询两个分区的数据(select × from table_name where partition_name='XXX'),发现新分区能够正常查询,历史分区依旧有问题。由此可见,查询出现的问题与数据文件本身无关,或者说数据文件本身是完好的
  4. 综上,我们可以认为是表的结构或者说是表的元数据更新有问题导致的历史分区数据在刷新之后无法正常查询。

0X02 解决

解决:
表元数据更新问题由于集中在历史分区,可以先通过drop partition的方式清理旧的元数据信息,然后再重新新建表分区ALTER TABLE table_name ADD PARTITION (partCol = 'value1') location 'loc1'; 。这样历史分区的数据就可以正常查询了。

0X03事后思考

由于hive数据的加载模式,它是会将表的元数据(记录在hive的管理RMDB,一般是mysql)和表数据(HDFS或者本机文件)分开存放,并且一般的ddl、dcl语句只对元数据进行检查、修改,并不会对表的数据进行强校验。而且不同分区的元数据分开记录,新增字段之后,只对之后的分区产生效应(比如10个字段增加到12个字段),而历史分区的元数据记录里面依旧记录着这些历史分区对应的字段只有10个,这也就是为什么需要我们把历史分区drop掉之后在重新新建,因为这样可以把另外2个新增字段信息添加到分区元数据记录中。
分布式的存储结构、处理思想,决定了数据在存放、计算时是需要划分小块后进行的,这样会导致了一些问题,比如块之间可能由于跨机器甚至跨机房导致的网络通讯滞后、元数据记录由于多次更改产生多条不一致记录,这些对会对数据的元数据一致性管理造成挑战。这也是造成这种加字段、刷新数据后,数据查不出来的问题的原因,而这类原因往往会比较超出我们的思维习惯,让第一次遇见这种问题的程序员感到匪夷所思,但我们如果能带入到分布式的思想中去思考,就能明朗。
所以,由此也引申出来了CAP原则,NoSQL或者是说分布式系统能且只能满足其中两个原则。往往我们需要通过了解分布式系统/组件/工具的特性,理清我们的需求之后再去选用适用的系统组件,而不是做出类似让hive去做事实计算(实际上是划分较小时间区间去做近实时的数据更新而已)、让hbase去做数据关联分析、让kafka做持久化存储的骚操作。理论上是可行,我本人也曾实践过前两种,但引出来的bug、问题、解决这些问题的脑力、时间成本远远超出你重新部署一块新的大数据组件比如spark,妄图通过一招鲜打遍天下无敌手是最蠢的,抽象到哲学层面可以一招走天下,但毕竟你是在工程层面,你还是考虑实践的成本和效果。
我认为程序员保持谦逊是很重要的,即使你很牛。谦虚可以让你认清你的环境、你所处的层面、你所要面对的挑战和收益、你缺点和擅长。我认识一个10年以上的oracle数据库开发,对已oracle本身无比熟悉,也很认同oracle的思想。但是总是跳不出这个框架,口头禅是“你这个大数据怎样怎样,以前oracle怎样怎样就处理好了,一点都不好用”。我这么写不是为了引战,hadoop也好oracle也好,其实都是工具、都有各自的优缺点,只要系统的优点是刚好能满足我当前最高优先级的需求且其缺点暴露出来的问题是当下能够容忍的,那么就是最好的工具,不管缺点会被放大多少倍,在这里田忌赛马、黑猫白猫才是中心思想。我也遇到“如何使用SQL快速实现聚类算法”的灵魂提问,这已经不是田忌赛马了,是关公战秦琼了。
是的,黑猫白猫理论是应用层面最好的标准。前提是保持谦逊、保持认真,不要闹关公战秦琼的笑话,这样我们才能不断做出大部分是有利自身、科技、社会的迭代。

0X04事后再补充

你以为文章已经结束了吗?我还想再写几句。
我记得上大学学计算机的时候我们老师就给我们讲了二分法,对于大部分人都是大一才接触计算机且听完老师讲解完还一知半解。老师当时语重心长:“现在没搞懂没关系,后面你一定要背下来,代码怎么实现的、思想是怎样的。”
我到现在也没背下来代码。但是思想我确实在一次次工作实践(打脸)中领悟了。二分其实更多的是告诉我们面对一个旁大的集合、旁大的任务,我们要去做适当的分解拆分成一份份小集合、小问题,然后逐个攻破。(还有递归思想也很重要)
工作中遇到的MVC分层、数仓分层、分布式思想无不散发出问题切分的光辉。
但是切分出来的小问题、任务都会越来越具象,以至于其执行步骤的通用性在下降,所以出现差异化,这也是既有NoSQL又有关系型DB的缘故、既有离线批处理又有流式计算、既有OLTP又有OLAP的原因。
众多组件的堆砌,无异增加了运维的成本,所以有了微服务、有了离线计算和流计算融合的Flink、有了NoSQL和SQL融合的谷歌Spanner、PingCAP的TiDB。
是谓合久必分、分久必合。
我们可以看到,科技发展史本身和历史进程是吻合的,很多技术、架构并不是一开始设计好的,而是根据需要不断改进、重新设计出来。往往对这个结论,有很多人持有不同看法,毕竟时间天马行空的科学研究、创造也很多,它们并不一定“接地气”。
其实它们也是符合我们需要的,只是目前自身所处环境、从众心理等困住思维的翅膀,我们暂时无法看到它的必要性。5G出来的时候也有很多人认为没有必要,毕竟现在4G已经足够快了甚至过剩了,现在看来,并不是网络传输技术超前了,是其他方面落后了。
对于成功,一个人的奋斗固然重要,但也要考虑历史的进程。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值