当Hive表使用中文列名时遇到的异常问题
2023-02-03 15:03:00.0
问题描述
使用Spark SQL将DataFrame(列名为中文)写入到Iceberg Hive Catalog中时,出现如下异常信息,并且写入失败:
“org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: MetaException(message:Add request failed : INSERT INTO COLUMNS_V2 (CD_ID,COMMENT,`COLUMN_NAME`,TYPE_NAME,INTEGER_IDX) VALUES (?,?,?,?,?) )” ......
实际上,如果直接在Hive中创建带有中文字段名称的表时,也会遇到这个异常信息。例如:
CREATE EXTERNAL TABLE stu( `商品ID` STRING, `库存数量` INT, `单价` DOUBLE ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' STORED AS TEXTFILE LOCATION 'hdfs://xueai8:8020/business'
问题剖析
从报错信息中分析,推断是在执行建表语句时,需要更新Hive的元数据,而在Hive的元数据进行更新时,需要向元数据存储数据库MySQL的hive数据库的COLUMNS_V2表中插入表结构信息。报错信息中说明:在向MySQL中hive数据库的表COLUMNS_V2中插入字段名称时出现了问题。
为了证明这个推测,登录MySQL服务器,查看数据库hive中的COLUMNS_V2表的创建语句,命令如下:
mysql> use hive; mysql> show create table COLUMNS_V2\G;
输出内容如下:
MariaDB [hive]> show create table COLUMNS_V2\G;
*************************** 1. row ***************************
Table: COLUMNS_V2
Create Table: CREATE TABLE `COLUMNS_V2` (
`CD_ID` bigint(20) NOT NULL,
`COMMENT` varchar(256) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`COLUMN_NAME` varchar(767) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`TYPE_NAME` mediumtext,
`INTEGER_IDX` int(11) NOT NULL,
PRIMARY KEY (`CD_ID`,`COLUMN_NAME`),
KEY `COLUMNS_V2_N49` (`CD_ID`),
CONSTRAINT `COLUMNS_V2_FK1` FOREIGN KEY (`CD_ID`) REFERENCES `CDS` (`CD_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.01 sec)
观察上面的输出内容,可以看到COLUMN_NAME字段的编码字符集为默认的latin1字符集,因此中文名无法识别。所以要想能识别中文字段名,需要将该字段的字符集编码改为utf8。
问题解决
通过SQL命令将COLUMN_NAME字段的字符集编码修改为utf8,命令如下:
mysql> alter table COLUMNS_V2 modify column COLUMN_NAME varchar(255) character set utf8 COLLATE utf8_general_ci not null;
然后再执行hive创建带有中文列名的表的时候,或者向Iceberg Hive Catalog中创建带有中文列名的表的时候,都可以正常执行了。