[1022]Hive insert 字段表错位

2023-11-06

Hive insert 字段表错位踩坑

1 问题描述

往 Hive 表 insert 数据后,查询时出现个别行字段错位,插入语句如下:

insert overwrite table A select col1,col2,col3 from table B where dayid = '';

首先测试源表数据查询:

select col1,col2,col3 from B

查询来的数据没发现有什么异常;照理说逐字段查出来没问题,再逐字段插入应该不会错位。实际上 hive 的 insert 跟想象中传统的 insert 不太一样。

2 排查过程

由于不是全表错位,而是个别行错位,首先根据关键字查询 hive 错位那行数据,导出文本到本地。肉眼查看发现有部分"乱码"(异常字符: ^M,如果经验丰富一眼就能看出这个是 \001,vim 下可以通过组合键 ctrl + a 输出),怀疑是异常字符导致,通过 linux od 命令查看 16 进制编码,如图所示:有好几个 \001 ,多么眼熟的数字啊 - 这是 hive 默认字段分隔符。

一般insert A from select B我们没有关注 A 表的字段分隔符,看到\001 直觉跟 A 表的字段分隔符有关:
查看 A 的表结构,字段分隔符默认的 \001。存储类型:textfile

进一步分析:textfile 是 hive 默认的存储结构,行存储,存储的实际数据结构跟表逻辑结构一致。导入数据时会直接把数据文件拷贝到 hdfs上不进行处理。源文件可以直接通过hadoop fs -cat 查看; 例如 text 字段分隔符: \001 , 换行符: \n,表在 hdfs 实际存储的格式为:

v1\001v2\001v3\n
v4\001v5\001v5

猜测字段值缺失错位的根源在于:文本中的不可见字符 \001 插入到表中,而表以 \001 作为字段分隔符,导致查询字段错位。

3 问题定位

再来看这条 SQL:

insert overwrite table A select col1,col2,col3 from table B where dayid = '';

我们可以还原这条 SQL 从插入到查询异常的全流程:

  1. 查询:select col1,col2,col3 from table B where dayid = ''; 查询出的数据按照 A 表的字段分隔符以及定义的换行符拼接起来。
  2. 插入:由于 A 表是 textfile ,直接把查询的数据 insert (append)到 hdfs 上
  3. 查询:由于多余的字段符 \001 被插入到 A 表中,查询的时候必然错乱。
4 解决方案
  • 入库前清洗掉数据中的 \001
  • 修改 A 表的存储格式为 orc 等(不用关心字段分隔符)
  • 修改 A 表字段分隔符为其他不可见字符

第一种方式可行且更加合理;
第二种方式可行,一种补救方案,但是 orc 等格式不支持 load 操作
第三种方式临时解决问题,不能根本上解决问题;

推荐解决方法

insert overwrite table A select 
regexp_replace(trim(col1),'\t|\n|\001|\r','') as col1,
regexp_replace(trim(col2),'\t|\n|\001|\r','') as col2,
regexp_replace(trim(col3),'\t|\n|\001|\r','') as col3
from table B where dayid = '';

hive的insert语句列顺序问题以及新增字段遇到的坑

讲问题之前,先简单创建一个表:

CREATE TABLE IF NOT EXISTS `my.test_table`(
  `col1` int COMMENT "第一列",
  `col2` int COMMENT "第二列"
)
COMMENT "测试表"
PARTITIONED BY (`pt` int COMMENT "测试分区")
ROW FORMAT SERDE
  "org.apache.hadoop.hive.ql.io.orc.OrcSerde"
STORED AS INPUTFORMAT
  "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"
OUTPUTFORMAT
  "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat";

初始表有col1,col2两列,pt分区只是为了对比结果

insert语句列顺序

hive不像mysql、oracle这些数据库一样在insert的时候可以指定字段,必须在插入的时候插入的是全字段。所以我一直以为可以通过指定插入数据的别名来改变插入字段的顺序,好吧,事实证明我是错的!

我们来简单作一个设想,假如我们执行以下的sql会发生什么:

insert overwrite table my.test_table partition(pt=1) select 2 as col2, 1 as col1 from my.online_table;

按常规逻辑来说,查询的时候应该是col1字段都为1,col2字段都为2。但是事实上执行

select col1, col2 from my.test_table;

结果是:

2    1
2    1
2    1
2    1
....

事实上,hive并不关心你执行insert语句所用的别名,别名代表的字段可以不存在,甚至比别名都可以相同。下面的语句执行也是一样的效果:

insert overwrite table my.test_table partition(pt=1) select 2 as invalid_col, 1 as invalid_col from my.online_table;

是不是觉得很惊喜。所以,请严格保证insert语句中的字段和建表语句中的字段的顺序一致!!!

对新增字段插入数据再查询发现是NULL

**hive比较特殊的地方,在于它的表结构和数据其实是分开的。**这个会导致,对hive分区表新增字段后,在执行插入分区的动作,会发现其实数据文件中已经有新字段值了,但是在查询的时候新字段的值还是显示为null。

例如我执行了下面的方法新增了一列col3:

alter table my.test_table add columns(col3 int comment '第三列')

然后想插入一些数据:

insert overwrite table my.test_table partition(pt=1) select 1 as col1, 2 as col2, 3 as col3 from my.online_table; 

结果查询col1,col2,col3发现结果其实是:

1    2    NULL
1    2    NULL
...1

这是因为你对表结构进行了改变,但是历史分区的数据却没有做改变(新增分区不会出现这个情况)。

为了解决上面的问题,可以采用两种方式:

  • 如果已经执行添加操作,并且没有带cascade,可以尝试下面的方法:
使用replace 恢复表结构,这样历史的分区数据都不会消失
alter table industry_db.product replace columns(product_name string comment ‘产品名’);
  • 在新增的时候加上cascade关键词
alter table my.test_table add columns(col3 int comment '第三列') cascade

官方文档描述如下:

The CASCADE|RESTRICT clause is available in Hive 1.1.0. ALTER TABLE ADD|REPLACE COLUMNS with CASCADE command changes the columns of a table’s metadata, and cascades the same change to all the partition metadata. RESTRICT is the default, limiting column changes only to table metadata.

如上所述,在1.1.0中表和分区的元数据就是分开处理的,对于在添加字段的时候没有指定的cascade的情况,在增加字段的时候添加CASCADE能同时更新表和分区

因为我们在重跑数据的时候,虽然HDFS上的数据更新了,但是我们查询的时候仍然查询的是旧的元数据信息(即Mysql中的信息)

注意:对于执行了add column语句之后新生成的分区,是不会有问题的,Hive会自动维护新分区中的元数据。

参考:https://www.cnblogs.com/fnlingnzb-learner/p/13472266.html
https://www.jianshu.com/p/568a43eb5114

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[1022]Hive insert 字段表错位 的相关文章

  • Vue笔记_03组件_transition组件(Vue内置组件)

    目录 transition组件 作用 过渡时机 语法1 语法2 使用 animation侦动画 使用 过渡动画 总结 逻辑 前后端配置 动态显示页面 transition组件 作用 transition组件的作用是 给 单个 元素 组件 添

随机推荐

  • Uncaught SyntaxError: Invalid or unexpected token

    报错原因 内含中文字符串或者中文的符号 解决方案 1 去除页面上中文符号 改成英文符号 2 特殊的情况 那我的报错原因来说一下 报错代码和背景 我在做js使用DOM元素做拼接 报了这个错误 Uncaught SyntaxError Inva
  • 使用循环打印三角型以及九九乘法表

    一 循环打印三角形 1 需求分析 需要用到双层for循环来实现 外层循环实现行数 内层循环实现每行的个数 外层每循环一次 就换一次行 内层循环打印的个数与外层循环的行数是相对应的 由于内层循环的个数和外层循环的行数一样 所以内部循环的判断条
  • Linux下C++开发笔记--解决报错error: redefinition of “xxx“

    1 报错截图 2 错误原因 对应的头文件被多次包含 3 解决方法 在头文件最上面加上以下代码 以避免被多次包含 pragma once
  • 原码,反码,补码的使用

    机器码 1 首先得知道 什么是机器码 将符号 数字化 的二进制数就叫做机器码 其中有两点 1 将符号数字化 也就是将 用数字0表示 用数字1表示 最高位表示符号位 2 必须是二进制数 因为计算机中所有的数据都是以二进制形式存储的 2 了解了
  • HBase主要运行机制(物理存储和逻辑架构)

    本节将对 HBase 的主要运行机制进行简单介绍 HBase 的物理存储 HBase 表中的所有行都是按照行键的字典序排列的 因为一张表中包含的行的数量非常多 有时候会高达几亿行 所以需要分布存储到多台服务器上 因此 当一张表的行太多的时候
  • 【MySQL高级篇笔记-数据库备份与恢复(下) 】

    此笔记为尚硅谷MySQL高级篇部分内容 目录 一 物理备份与逻辑备份 二 mysqldump实现逻辑备份 1 备份一个数据库 2 备份全部数据库 3 备份部分数据库 4 备份部分表 5 备份单表的部分数据 6 排除某些表的备份 7 只备份结
  • 【VSCode】Windows系统的WSL无法启动vscode问题

    在WSL环境中无法启动vscode时 有可能是 WSL 插件的影响 可以使用下面的步骤来解决 Open VS Code on Windows Open Extensions and then search on WSL It should
  • Qt使用Qt Designer进行界面设计

    上一章我们使用代码直接进行界面设计 这一章我们使用Qt Designer进行界面设计 简单直接 所见即所得 大大提高了工作效率 特别是对于复杂界面 1熟悉Qt Designer Qt Designer是Qt专为界面设计做的软件 使得用户能够
  • 使用Python和OpenCV进行图像拼接和全景图构建

    使用Python和OpenCV进行图像拼接和全景图构建 1 效果图 2 原理及步骤 3 源码 3 1 拼接类源码 3 2 拼接用到的工具类 3 3 叠加多张图像源码 参考 这篇博客将介绍如何使用OpenCV执行图像拼接和全景构建 即给定两个
  • Hana Studio开发简介

    Hana Studio作为SAP官方的IDE 工具 推出也有一段时间了 就目前使用的情况来看 如果是做常规S 4开发 SAP GUI还是首要选择 一 IDE安装路径 链接 https pan baidu com s 1qMg8duocTa3
  • pyqt5实现按钮单窗口多页面切换

    1 使用QT Designer进行设计 创建一个MainWindow 从左侧选出Push Button Stacked Widget分别拖到我们的MainWindow里 怕看不见Stacked Widget 给他上个色 在QT Design
  • vant-weapp Area 省市区选择的使用及遇到的坑

    json中 导入 van area vant weapp area index 基础用法
  • SpringCloud gateway (史上最全)

    1 1 SpringCloud Gateway 简介 SpringCloud Gateway 是 Spring Cloud 的一个全新项目 该项目是基于 Spring 5 0 Spring Boot 2 0 和 Project Reacto
  • Kubernetes踩坑(二): Service IP(LVS)间断性TCP连接故障排查

    问题阶段 一 用户反应某个redis使用卡顿 连接该redis服务使用的是svc代理 即ipvs snat的方式 ipvsadm L发现 VIP收到的6379端口的数据包 会以rr的方式分别转发到pod的80 6379端口上 相当于会有50
  • mysql增加分区

    增加分区 是修改原有分区 从而替换现有分区 ALTERTABLE xxx表 PARTITION BY RANGE COLUMNS CREATE TIME PARTITION p20210901 VALUES LESS THAN 2021 1
  • 【华为OD机试c++】最长广播效应【2023 B卷

    题目描述 某通信网络中有N个网络结点 用1到N进行标识 网络中的结点互联互通 且结点之间的消息传递有时延 相连结点的时延均为一个时间单位 现给定网络结点的连接关系link i u v 其中u和v表示网络结点 当指定一个结点向其他结点进行广播
  • linux grep 带空格的内容,或者搜索多个单词,一段话

    错误示范 more xxx log grep UPDATE user info 正确方法 more xxx log grep UPDATE user info
  • 第23讲 Python range 数据类型

    您的 关注 和 点赞 是认可 是支持 是动力 如意见相佐 可留言 本人必将竭尽全力试图做到准确和全面 终其一生进行修改补充更新 本文首发在IT羊资源网 IT羊资源网 网址 https www ityangzy com IT羊资源网是IT世界
  • GB9706.1-2007+2020和IEC60601-1:2005 3.0+2012 3.1标准主要差异解析

    目录 GB9706 1 2007医用电气设备 第1部分 安全通用要求 GB9706 1 2020医用电气设备 第1部分 基本安全和基本性能的通用要求 IEC60601 1 第二版和第三版差异 1 最关键变化 2 新术语名词引用 3 设备分类
  • [1022]Hive insert 字段表错位

    文章目录 Hive insert 字段表错位踩坑 1 问题描述 2 排查过程 3 问题定位 4 解决方案 hive的insert语句列顺序问题以及新增字段遇到的坑 insert语句列顺序 对新增字段插入数据再查询发现是NULL Hive i