Hive MetaStore建表与修改表分析

问题

使用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数据库

updatedupdated2023-12-062023-12-06