1、前言

在hive的开发交互中,有时需要获取hive表数据在hdfs中的location位置、或者获取hive的文件存储格式、使用的压缩算法,甚至是表中的字段类型、字段注释、字段约束、表中是否有数据、数据大小、文件数等信息。这些信息hive没有提供统一的入口,即使直连hive元数据存储的mysql数据库,也很难一次性拿到这些数据。

但是hive提供的desc命令则可以一次性获取所有的这些信息,例如:

desc formatted tableName

(注:我这里用的是2.3.9版本,加不了约束,所以详细信息里面看不到约束) 

不过,虽然desc可以一次性获取所有的这些信息,但是这些信息并不是封装好的,需要通过resultSet一行行读取。以前为了获取hive表存储地址,我解析过一次,但那个不够通用。所以这次准备封装一个通用的解析,避免自己重复造轮子。

2、解析代码

public static Map getTableInfo(ResultSet resultSet) throws Exception {

Map result = new HashMap<>();

// 定义多个集合用于存储hive不同模块的元数据

Map detailTableInfo = new HashMap<>();

Map tableParams = new HashMap<>();

Map storageInfo = new HashMap<>();

Map storageDescParams = new HashMap<>();

Map> constraints = new HashMap<>();

List> columns = new ArrayList<>();

List> partitions = new ArrayList<>();

Map moduleMap = getDescTableModule();

// 解析resultSet获得原始的分块数据

String infoModule = "";

while (resultSet.next()) {

String title = resultSet.getString(1).trim();

if (("".equals(title) && resultSet.getString(2) == null) || "# Constraints".equals(title)) continue;

if (moduleMap.containsKey(title)) {

if ("partition_info".equals(infoModule) && "col_name".equals(moduleMap.get(title))) continue;

;

infoModule = moduleMap.get(title);

continue;

}

String key = null;

String value = null;

switch (infoModule) {

case "col_name":

Map map = new HashMap<>();

int colNum = resultSet.getMetaData().getColumnCount();

for (int col = 0; col < colNum; col++) {

String columnName = resultSet.getMetaData().getColumnName(col + 1);

String columnValue = resultSet.getString(columnName);

map.put(columnName, columnValue);

}

columns.add(map);

break;

case "table_info":

key = resultSet.getString(1).trim().replace(":", "");

value = resultSet.getString(2).trim();

detailTableInfo.put(key, value);

break;

case "table_param":

key = resultSet.getString(2).trim().replace(":", "");

value = resultSet.getString(3).trim();

tableParams.put(key, value);

break;

case "storage_info":

key = resultSet.getString(1).trim().replace(":", "");

value = resultSet.getString(2).trim();

storageInfo.put(key, value);

break;

case "storage_desc":

key = resultSet.getString(2).trim().replace(":", "");

value = resultSet.getString(3).trim();

storageDescParams.put(key, value);

break;

case "not_null_constraint":

Map notNullMap = constraints.getOrDefault("notnull", new HashMap<>());

if ("Table:".equals(title.trim())) resultSet.next();

String notNullConstraintName = resultSet.getString(2).trim();

resultSet.next();

key = resultSet.getString(2).trim();

notNullMap.put(key, notNullConstraintName);

constraints.put("notnull", notNullMap);

break;

case "default_constraint":

Map defaultMap = constraints.getOrDefault("default", new HashMap<>());

if ("Table:".equals(title.trim())) resultSet.next();

String defaultConstraintName = resultSet.getString(2).trim();

resultSet.next();

key = resultSet.getString(1).trim().split(":")[1];

value = resultSet.getString(2).trim();

int valueIndex = value.indexOf(":");

value = value.substring(valueIndex + 1);

defaultMap.put(key + "_constraintName", defaultConstraintName);

constraints.put("default", defaultMap);

break;

case "partition_info":

Map partitionMap = new HashMap<>();

int partitionColNum = resultSet.getMetaData().getColumnCount();

for (int col = 0; col < partitionColNum; col++) {

String columnName = resultSet.getMetaData().getColumnName(col + 1);

String columnValue = resultSet.getString(columnName);

partitionMap.put(columnName, columnValue);

}

partitions.add(partitionMap);

break;

default:

System.out.print("unknown module,please update method to support it : " + infoModule);

}

}

result.put("columns",columns);

result.put("detailTableInfo",detailTableInfo);

result.put("tableParams",tableParams);

result.put("storageInfo",storageInfo);

result.put("storageDescParams",storageDescParams);

result.put("constraints",constraints);

result.put("partitions",partitions);

return result;

}

private static Map getDescTableModule() {

Map descTableModule = new HashMap<>();

descTableModule.put("# col_name", "col_name");

descTableModule.put("# Detailed Table Information", "table_info");

descTableModule.put("Table Parameters:", "table_param");

descTableModule.put("# Storage Information", "storage_info");

descTableModule.put("Storage Desc Params:", "storage_desc");

descTableModule.put("# Not Null Constraints", "not_null_constraint");

descTableModule.put("# Default Constraints", "default_constraint");

descTableModule.put("# Partition Information", "partition_info");

return descTableModule;

}

上面的代码基本上覆盖了所有常用的数据模块,如果有代码中没解析到的模块,则依据代码逻辑添加对应的模块名称和case模块即可。代码很简单,主要就是解析时要细心。

3、测试

下面是我新建的一个简单测试demo,有兴趣的可以简单看下:

1)引入依赖

org.apache.hive

hive-jdbc

2.3.9

2)编辑代码

public static void main(String[] args) {

try {

String driverName = "org.apache.hive.jdbc.HiveDriver";

Class.forName(driverName);

Connection conn = DriverManager.getConnection("jdbc:hive2://192.168.71.135:10000/test_db");

String sql = "desc formatted test_table";

PreparedStatement ps = conn.prepareStatement(sql);

ResultSet resultSet = ps.executeQuery();

Map result = getTableInfo(resultSet);

System.out.println(result.size());

} catch (Exception throwables) {

throwables.printStackTrace();

}

}

3)结果显示

 可以看到除了约束之外,其它的数据都正常的存入到了对应的集合中。(我测试用的2.3.9版本的约束创建有问题,但是在3.1.0版本中创建约束是正常的)。

4、总结

上面是我根据自己的需求使用进行的代码编辑,其基本包含了全部的表信息。但是也有可能有没考虑周到的地方,比如我一开始没考虑到多个同种约束的问题,在使用中遇到问题了又来重新更新了文章中的代码。所以如果使用中有些地方解析不对,可能需要您根据自己的实际场景再进行改写。

推荐文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: