Author:Christopher_L1n | 优快云 Blog | 未经允许,禁止转载
Hive -> Hive 集群间迁移数据库表
阅读提示
- 为了代码易读性,脚本中加入冗余的参数赋值,可删除,直接使用$1、$2…等。
- 为了一步步检查输出是否正确,脚本中使用了大量临时文件,请读者自行精简。
- 尽可能在各小节尾整理各节的脚本。
- 本教程采用方案是直接覆盖目标库表的,类似overwrite。若要增量更新数据,可参考写在后面的方式,自行限定过滤条件,更新目标表。
建库
可通过下述语句在目标集群建库:
CREATE DATABASE IF NOT EXISTS dbname;
若无权限,可先获取ADMIN权限:
SET ADMIN;
整理为shell脚本:
#! /bin/bash
dbname=$1
tmpPath=$2
echo "CREATE DATABASE IF NOT EXISTS $dbname;" > tmpPath
beeline -f $tmpPath
获取该库下所有表名
可通过下述语句在源集群执行获取所有源库的所有表名:
USE dbname;
SHOW TABLES;
将上述文件写入hiveShowTB文件后,可写shell脚本:
#! /bin/bash
# $1 应为hiveShowTB文件,$2为输出文件,二者都建议绝对路径
beeline -f $1 > $2
此为输出:
+----------------+--+
| tab_name |
+----------------+--+
| tbname0 |
| tbname1 |
+----------------+--+
应删除无用字符,可使用sed处理:
# $hiveShowTB即上述hiveShowTB文件
cat $hiveShowTB | sed '/\+-/d' | sed 's/|//g' | sed 's/ //g' | sed 's/^$//g' > output
将本节的脚本整理一下:
#! /bin/bash
sqlTmp=$1
dbname=$2
tablesTmpOutput=$3
tablesOutput=$4
echo "USE $dbname;" > $sqlTmp
echo "SHOW TABLES;" >> $sqlTmp
beeline -f $sqlTmp > $tablesTmpOutput
cat $tablesTmpOutput | sed '/\+-/d' | sed 's/|//g' | sed 's/ //g' | sed 's/^$//g' > $tablesOutput
获取建表语句
在源集群执行下述语句,可获得指定表的建表语句:
USE dbname;
# 会丢失COMMENT注释内容,注释需要使用DESC TABLE tbname;来获取
# 本教程只是为了尽快写一个简单的拷贝工具,请读者自行实现获取COMMENT注释内容
SHOW CREATE TABLE tbname;
整理为shell脚本:
#! /bin/bash
dbname=$1
# 存放临时文件和建表文件的路径
storagePath=$2
# 指定库下所有表名的文件,由上一节脚本生成
tables=$3
cmdTmp="$storagePath/$dbname.cmdtmp"
ctTmp="$storagePath/$dbname.cttmp"
create="$storagePath/$dbname.create"
# 生成获取建表信息的SQL语句,整合到文件中
echo "USE $dbname;" > $cmdTmp
while read tablename
do
echo "SHOW CREATE TABLE $tablename;" >> $cmdTmp
done < $tables # $tables 为 纯表名文件
# 获取建表信息
beeline -f $cmdTmp > $ctTmp
# 删去无用字符
cat $tbTmp | sed '/Connecting to/d' | sed '/Debug is/d' | sed '/Acquire TGT/d' | sed '/Principal is/d' | sed '/Commit /d' | sed '/Connectd to/d' | sed '/Transaction isolation/d' | sed '/rows selected/d' | sed '/jdbc:hive2/d' | sed '/Closing:/d' | sed '/\+-/d' | sed 's/|//g' | sed '/createtab_stmt/d' | sed '/^$/d' > $create
即获得dbname.create文件。
建表
# 可添加到上一节的脚本末尾
beeline -f 上述dbname.create文件
有些表有依赖,若有表未成功创建,可再执行一遍,因此建议手动执行这节代码,而不是添加到上一节脚本中。
准备数据
配置完集群间互信,使用hadoop distcp在集群间拷贝表数据,拷贝直接覆盖目标库的各表文件。
拷贝表数据后,恢复元数据即可完成拷贝表数据:
#! /bin/bash
# 第一个参数:数据库名
dbname=$1
# 第二个参数:纯表名文件
tbListFile=$2
# 存放临时文件、日志和结果文件的路径,建议绝对路径
storagePath=$3
rpPath="$storagePath/$dbname.repair"
logPath="$storagePath/$dbname.log"
echo "USE $dbname;" > $rpPath
while read tablename
do
echo "MSCK REPAIR TABLE $tablename;" >> $rpPath
done < $tbListFile
# 这里的日志有问题,没有把建表时的输出打进来
beeline -f $rpPath >> $logPath
写在后面
如果采用的是将源集群的数据打包为dat、csv等文件,可以通过下述语句加载数据:
LOAD DATA INPATH "/user/hive/.../xxx.dat" INTO TABLE tablename;
- 若载数出现异常:
FAILED: SemanticException Unable to load data to destination table. Error: The file that you are trying to load does not match the file format of the destination table.
这是由于SequenceFile表不能使用LOAD指令加载数据,它只能导入sequence类型的数据。
-
解决方法
新建一张临时表,以STORED AS TEXTFILE限定存储方式,然后将数据载入临时表,再由临时表复制到目标表:
CREATE TEMPORARY TABLE tmptablename LIKE tablename STORED AS TEXTFILE;
LOAD DATA INPATH "hdfsfilepath" INTO TABLE tmptablename;
INSERT INTO TABLE tablename SELECT * FROM tmptablename;