问题
使用Hive MetaStore(这里指的是通过thrift连接hiveserver) Create table 和 Alter table的时候遇到一个问题
建表时指定的location为 /mnt/dfs/xxx,实质上使用hiveMetastore会帮你做一个转换,最后location变成 hdfs://hostname:port/mnt/dfs/xxx的路径
但在修改表的时候,却不会帮你做这样的转换!!坑爹啊。。你指定的是什么就是什么~
注:通过hive命令行方式执行sql命令建表也是这样,不过修改表的时候,location必须是这样的路径hdfs://hostname:port/mnt/dfs/xxx才可以修改成功,否则报错。
分析问题
从代码入手吧。。
进入这个目录
hive-0.7.1-cdh3u3\src\metastore\src\java\org\apache\hadoop\hive\metastore
这里都是hiveserver的代码了。
打开HiveMetaStore.java代码,咱们直奔主题,找create_table和alter_table去
public void create_table(final Table tbl) throws AlreadyExistsException, MetaException, InvalidObjectException { ... create_table_core(ms, tbl); |
调用了create_table_core(ms, tbl);继续
private void create_table_core(final RawStore ms, final Table tbl) throws AlreadyExistsException, MetaException, InvalidObjectException { //检查了一些名称,列名,分区之类的 //... ms.openTransaction(); //.... if (!TableType.VIRTUAL_VIEW.toString().equals(tbl.getTableType())) { if (tbl.getSd().getLocation() == null || tbl.getSd().getLocation().isEmpty()) { tblPath = wh.getDefaultTablePath( tbl.getDbName(), tbl.getTableName()); } else { if (!isExternal(tbl) && !MetaStoreUtils.isNonNativeTable(tbl)) { LOG.warn("Location: " + tbl.getSd().getLocation() + " specified for non-external table:" + tbl.getTableName()); } // 主要就是这里啦!getDnsPath!!!帮我们把dataurl补全 tblPath = wh.getDnsPath(new Path(tbl.getSd().getLocation())); } tbl.getSd().setLocation(tblPath.toString()); } //... ms.createTable(tbl); } |
因为我们的location不为空~所以..
主要就是这一句:tblPath = wh.getDnsPath(new Path(tbl.getSd().getLocation()));
看看getDnsPath()做了什么,打开代码Warehouse.java
public Path getDnsPath(Path path) throws MetaException { FileSystem fs = getFs(path); return (new Path(fs.getUri().getScheme(), fs.getUri().getAuthority(), path .toUri().getPath())); } |
就帮我们做了些转换。。。我们建表看到的hdfs://hostname:port就是这里加上的。
再来看一下alter_table
public void alter_table(final String dbname, final String name, final Table newTable) throws InvalidOperationException, MetaException { \\... alterHandler.alterTable(ms, wh, dbname, name, newTable); |
跳入这个类HiveAlterHandler.java,只有一个方法:
public void alterTable(RawStore msdb, Warehouse wh, String dbname, String name, Table newt) throws InvalidOperationException, MetaException { //这里主要判断表名有没有改 //如果改了分区字段则抛错误 //如果改了表名但location没改或者为空,并且不是外部表,则把数据给移了~ //最后,直接的alterTable了。。?虾米,location就这样保存进去了?! // now finally call alter table msdb.alterTable(dbname, name, newt); // commit the changes success = msdb.commitTransaction(); } |
location没做什么处理就保存进去了。。。
RawStore是什么东西?代码中很多用了反射的方式调用。。貌似实质上是ObjectStore.java类。。
这个类使用jdo来操作metastore数据库
7条评论
You can leave the first : )