Impala版本: 2.7.0+cdh5.10.2+0
Kudu版本:1.4.0+cdh5.12.0+0
Hue版本:3.9.0+cdh5.10.2+4153
因业务需要,需要在kudu中创建含有中文字段的表。原来的方案是直接在Hue中Impala查询界面执行建表脚本,但是表中含有中文字段时,就会执行出错,建表脚本和出错信息如下:
建表脚本:
create table if not exists kudu_test(
`id` string,
`字段1` string,
`字段2` string,
PRIMARY KEY (id)
)
PARTITION BY HASH (id) PARTITIONS 4
stored as kudu;
错误信息:
- AnalysisException: Invalid column/field name: 字段1
上述错误为Impala抛出的异常,相关源码如下:
public void analyze(Analyzer analyzer) throws AnalysisException {
// Check whether the column name meets the Metastore's requirements.
if (!MetaStoreUtils.validateName(colName_)) {
throw new AnalysisException("Invalid column/field name: " + colName_);
}
if (typeDef_ != null) {
typeDef_.analyze(null);
type_ = typeDef_.getType();
}
Preconditions.checkNotNull(type_);
Preconditions.checkState(type_.isValid());
if (hasKuduOptions()) {
Preconditions.checkNotNull(analyzer);
analyzeKuduOptions(analyzer);
}
// Check HMS constraints on comment.
if (comment_ != null &&
comment_.length() > MetaStoreUtil.CREATE_MAX_COMMENT_LENGTH) {
throw new AnalysisException(String.format(
"Comment of column '%s' exceeds maximum length of %d characters:\n" +
"%s has %d characters.", colName_, MetaStoreUtil.CREATE_MAX_COMMENT_LENGTH,
comment_, comment_.length()));
}
}
为了能够在Kudu中创建含中文字段的表,并通过Impala查询该表,可以有以下方案:
方案一:修改Impala源码。但是鉴于本人能力有限,担心源码修改后,会产生其他未知异常,因此放弃该方案。
方案二:通过kudu的API创建含中文字段的表,然后在Impala中创建外部表进行关联。下面详细介绍该方案。
1、调用Kudu的JavaAPI,创建含有中文字段的表,代码如下:
public static void createTable(){
KuduClient client = new KuduClient.KuduClientBuilder("127.0.0.1:7051").build();
List<ColumnSchema> columns = new LinkedList<ColumnSchema>();
columns.add(newColumn("id", Type.STRING, true));
columns.add(newColumn("字段1", Type.STRING, false));
columns.add(newColumn("字段2", Type.STRING, false));
Schema schema = new Schema(columns);
CreateTableOptions options = new CreateTableOptions();
// 设置表的replica备份和分区规则
List<String> parcols = new LinkedList<String>();
parcols.add("id");
// replica数量
options.setNumReplicas(3);
// hash分区的列
options.addHashPartitions(parcols, 10);
try {
client.createTable("kudu_test", schema, options);
} catch (KuduException e) {
e.printStackTrace();
}finally {
try {
client.close();
} catch (KuduException e) {
e.printStackTrace();
}
}
}
2、在Imapla中创建上述Kudu表的外部表,脚本如下:
CREATE EXTERNAL TABLE IF NOT EXISTS kudu_test
STORED AS KUDU
TBLPROPERTIES (
'kudu.table_name' = 'kudu_test'
);
3、当查询上述外部表的时候会有如下错误信息:
- AnalysisException: Failed to load metadata for table: 'kudu_test' CAUSED BY: TableLoadingException: Add request failed : INSERT INTO `COLUMNS_V2` (`CD_ID`,`COMMENT`,`COLUMN_NAME`,`TYPE_NAME`,`INTEGER_IDX`) VALUES (?,?,?,?,?)
这是因为Impala在存储kudu表的元数据信息时,原数据表的字段编码不支持中文导致的。以下是COLUMNS_V2表的相关信息
4、解决Impala元数据不支持中文
找到Imapla的元数据库中(我的元数据库名为metastore),在该元数据库修改COLUMNS_V2表中字段的编码格式,可以执行如下SQL:
ALTER TABLE `COLUMNS_V2` CHANGE `COMMENT` `COMMENT` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL;
ALTER TABLE `COLUMNS_V2` CHANGE `COLUMN_NAME` `COLUMN_NAME` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;
ALTER TABLE `COLUMNS_V2` CHANGE `TYPE_NAME` `TYPE_NAME` VARCHAR(4000) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL;
执行完上述SQL,刷新下Impala的元数据,就能在Impala中查询含有中文字段的kudu表了。