本文主要目的是为Hive的迁移提供一些参考。因实际生产环境各异,建议迁移前慎重评估,细致测试迁移方案,再进行最终的迁移及割接。
目录
1 Hive的架构和工作原理
2 Hive迁移方案
2.1 迁移准备
2.2 迁移步骤
2.3 HDFS迁移方案
2.3.1 迁移HDFS数据
2.3.2 HDFS数据一致性校验
2.4 Hive元数据迁移方案
2.4.1 迁移Hive 元数据
2.4.2 修正Hive 元数据中与HDFS路径相关的信息
2.5 迁移验证
2.5.1 基础验证
2.5.2 业务验证
3 Hive迁移测试
3.1 准备测试环境
3.2 构造常用hive表及数据
3.2.1 准备数据
3.2.2 创建Hive库
3.2.3 创建Hive表并灌入数据
3.3 HDFS迁移
3.3.1 迁移HDFS数据
3.3.2 HDFS数据一致性校验
3.4 Hive元数据迁移
3.4.1 迁移Hive元数据
3.4.2 修正Hive 元数据中与HDFS路径相关的信息
3.5 迁移验证
3.5.1 基础验证
3.5.2 业务验证
3.6 构造大量表和海量数据进行迁移测试
1 Hive的架构和工作原理
Hive 是基于Hadoop之上的数仓,便于用户可以基于SQL(Hive QL)进行数据分析,其架构图如下:
从上图可知,Hive主要用来将建立结构化数据库和后端分布式结构化文件的映射,以及把SQL语句转换为MapReduce(目前还支持Spark等执行引擎)任务,以便进行分布式查询分析。
具体分布式文件的存储、分布式计算的执行等均由后端的Hadoop来承接,如下图所示:
2 Hive迁移方案
基于Hive的架构图可知,在新老两个Hive集群之间进行迁移时,需要迁移Hive 元数据以及存储在HDFS/HBase上的文件数据,并调整元数据以适应新集群环境。本文主要讨论Hive 元数据 和 HDFS的迁移。两部分数据的说明如下:
1. Hive 元数据:用来存储hive 关系型数据库和HDFS的映射关系;
2. HDFS文件:用来保存实际数据文件;
需要针对以上两部分数据,分别考虑迁移方案。
2.1 迁移准备
1. 网络打通
通过专线或者VPN打通源集群和目标集群的网络,使得源集群中所有服务器可以和目标集群所有服务器通信,方便后续进行数据拷贝。
2.2 迁移步骤
1) 先迁移HDFS文件
通常HDFS数据体量较大,迁移时间较长,所以建议先迁移HDFS文件
2) 再迁移Hive 元数据
HDFS文件完成全量迁移后,即可以考虑大数据集群停止新的数据写入。 停止数据写入后,即可开始迁移Hive 元数据以及迁移增量的HDFS数据(HDFS全量迁移期间很可能有新数据写入,业务团队根据数据写入情况评估)
2.3 HDFS迁移方案
2.3.1 迁移HDFS数据
2.3.1.1 迁移工具介绍
使用 HDFS DistCp 远程分布式复制数据到目标新集群。DistCp是一个专门用于集群内部和跨集群服务数据的工具,底层利用MapReduce把数据复制拆分为Map任务,进行分布式拷贝。2.8.5版本的官方参考资料:https://hadoop.apache.org/docs/r2.8.5/hadoop-distcp/DistCp.html
HDFS DistCp跨集群复制数据时主要需要指定的命令参数及其功能如下:
-i 忽略拷贝失败的MR任务,让远程拷贝可以执行结束。并会保存拷贝失败的日志。
-log <logdir> DistCp会在map的输出中记录所有被拷贝文件,当map任务失败并且被再次执行时,日志中不会保存改文件记录;(当前在hadoop 2.8.5版本中测试 -log 参数不生效)
-filters 过滤掉某些文件,支持正则表达式
-update 1)源和目标文件长度或内容不同:源文件覆盖目标文件;2)目标侧文件不存在:拷贝源文件到目标集群
-delete 删除目标端有而源端没有的文件,-delete只有在使用 –update 或 –overwrite的时候生效
2.3.1.2 迁移准备
1. 停止源和目标HDFS相关文件的写入操作
使用DistCp进行数据复制的前提是:源和目标HDFS中的文件都不能在写的状态,否则DistCp拷贝可能会失败。
2. 本方案仅假设所有Hive对应的HDFS数据都存储在HDFS的 /apps/hive/warehouse/ 目录下,若Hive涉及外表或其他非存储在/apps/hive/warehouse/路径的文件,请依据相同方法进行迁移
2.3.1.3 全量迁移
登录Master节点,切换到hadoop用户:
su hadoop
执行远程分布式全量数据拷贝:
hadoop distcp -i -log /home/hadoop/logs 源HDFS集群访问域名或IP:端口号/apps/hive/warehouse/ 目标HDFS集群访问域名或IP:端口号/apps/hive/warehouse/
2.3.1.4 增量迁移
登录Master节点,切换到hadoop用户:
su Hadoop
执行远程分布式增量数据拷贝:
hadoop distcp -i -delete -log /home/hadoop/logs -update 源HDFS集群访问域名或IP:端口号/apps/hive/warehouse/ 目标HDFS集群访问域名或IP:端口号/apps/hive/warehouse/
2.3.2 HDFS数据一致性校验
HDFS数据迁移后,利用HDFS可以在3个层面进行数据一致性的校验:
1. 校验 HDFS 数据目录文件数量是否一致
如果目录数、文件数、字节数均一致,则可以认为Hive对应的HDFS文件已经迁移完成,且数据一致
2. 校验 HDFS 数据目录文件列表是否一致
若希望进一步校验是否所有文件都已迁移,则可以输出Hive对应的HDFS的数据目录和文件的列表,并对比是否一致
3. 校验 HDFS 文件内容是否一致
在某些情况下,需要对单个文件的内容进行一致性校验。此时可以使用HDFS自带的checksum工具进行校验,若源和目标文件的checksum相同,则迁移完成且数据一致;否则需要分析原因,并重新进行迁移。
2.3.2.1 校验 HDFS 数据总体是否一致
查看源和目标HDFS集群的目录数、文件数、字节数是否一致:
利用hadoop fs –count命令来统计目录数,文件数,字节数,当前场景可以使用到的命令参数如下:
-v displays a header line
-x excludes snapshots from the result calculation
即命令为:hadoop fs -count -v -x /apps/hive/warehouse
#官方参考文档(Hadoop2.8.5)https://hadoop.apache.org/docs/r2.8.5/hadoop-project-dist/hadoop-common/FileSystemShell.html#count
2.3.2.2 校验 HDFS 目录和文件列表是否一致
对比源和目标HDFS集群的目录和文件列表是否一致:
利用hadoop fs –ls来输出目录和文件列表,并使用diff工具进行对比是否一致。当前场景hadoop fs –ls命令可以使用到的参数如下:
-R: Recursively list subdirectories encountered. 递归子目录,列出所有子文件目录和文件
-C: Display the paths of files and directories only. 输出结果不显示时间、副本数等与文件列表无关的信息列
#官方参考文档(Hadoop2.8.5):https://hadoop.apache.org/docs/r2.8.5/hadoop-project-dist/hadoop-common/FileSystemShell.html#ls
在源和目标集群分别执行如下命令:
在源集群切换到root用户,执行:hadoop fs -ls -R -C /apps/hive/warehouse > srcfilelist
在目标集群切换到root用户,执行:hadoop fs -ls -R -C /apps/hive/warehouse > dstfilelist
得到文件和目录列表后,放到同一台机器上,使用diff命令进行比较:
当前场景可使用到的diff 命令相关重要参数:
-s --report-identical-files Report when two files are the same
--normal Output a normal diff.
#当源和目标集群文件列表相同时
[root@P4anyrQH-Master1 ~]# diff srcfilelist dstfilelist -s --normal
Files srcfilelist and dstfilelist are identical
#当源和目标集群文件列表不同时
[root@P4anyrQH-Master1 ~]# diff srcfilelist dstfilelist -s --normal
65,66c65
< /apps/hive/warehouse/user_info_db.db/user_tbl_ext_skewed_list_bucketing/age=34/000000_1
< /apps/hive/warehouse/user_info_db.db/user_tbl_ext_skewed_list_bucketing/age=35
---
> /apps/hive/warehouse/user_info_db.db/user_tbl_ext_skewed_list_bucketing/age=40
其中“65,66c65”中c前后分别为,源文件与目标文件内容不同的行,所在的行数
< 代表源文件与目标文件不同的内容
> 代表目标文件与目标文件不同的内容
2.3.2.3 校验 HDFS 文件内容是否一致
对比源和目标HDFS文件内容是否一致:
利用HDFS自带的checksum命令hadoop fs -checksum来校验单个文件checksum
#官方参考文档(Hadoop2.8.5):https://hadoop.apache.org/docs/r2.8.5/hadoop-project-dist/hadoop-common/FileSystemShell.html#checksum
举例:
#查看源端文件MD5值
[hadoop@P4anyrQH-Master1 logs]$ hadoop fs -checksum /apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0
/apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0 MD5-of-0MD5-of-512CRC32C 0000020000000000000000000a59f8a9ab89996e42566969734e21ee
#查看目标端文件MD5值
[root@iQotdoaa-Master1 ~]# hadoop fs -checksum /apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0
/apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0 MD5-of-0MD5-of-512CRC32C 0000020000000000000000000a59f8a9ab89996e42566969734e21ee
#MD5值相同
2.4 Hive元数据迁移方案
因Hive 元数据中存储了与HDFS路径相关的信息,所以Hive的元数据的迁移工作分为两部分:
1、 迁移Hive 元数据数据到新集群
2、 修正Hive 元数据中与HDFS路径相关的信息
2.4.1 迁移Hive 元数据
2.4.1.1 迁移Hive 元数据
Hive 的 元数据 通常存储在MySQL中,主要有以下两种方式进行迁移
1. 在线迁移:主从同步的迁移方案,解决了元数据迁移的全量+增量的问题
2. 离线迁移:利用mysqldump进行导入导出
离线迁移MySQL的简要操作步骤如下:
1、 使用离线迁移前,需要先确保源集群不再写入元数据。即停止Hive库、表、视图等相关的写操作
2、 从源集群导出元数据
mysqldump -hlocalhost -uhive -p --databases hive > hive_bk.sql
3、 导入元数据到目标集群
mysql -hlocalhost -uhive –p
mysql> source hive_bk.sql
2.4.1.2 校验新老集群Hive 元数据一致性
利用MySQL自带表级checksum工具,建议同版本之间使用,并且大数据量的表做checksum会对库的性能有一定影响,建议测试评估后使用。此处京东云团队对此封装了checksum工具,可以方便进行数据库级别的对比。使用说明如下:
# 下载 checksum 工具
wget "https://mysql-documents.s3.cn-north-1.jdcloud-oss.com/checksum_table" -O ./checksum_table
注意:此工具需安装在一台服务器上,并确保此服务器可以和源和目标MySQL均可通信
# 授权
chmod +x checksum_table
# 数据校验
# --ws 并发度
./checksum_table --src-host mysql-xxx.rds.jdcloud.com --src-user 'user-xxx' --src-pass 'password-xxx' --dest-host mysql-xxx.rds.jdcloud.com --dest-user 'user-xxx' --dest-pass 'password-xxx' --ws 30 --database 'dbname-xxx'
eg:
# source checksum: 源表 checksum 值
# dest checksum: 目的表 checksum 值
# result: 校验结果
+--------+-------+-----------------+---------------+--------+
| schema | table | source checksum | dest checksum | result |
+--------+-------+-----------------+---------------+--------+
| dbtest | tb_1 | 1081724441 | 1081724441 | true |
+--------+-------+-----------------+---------------+--------+
如果出现数据库表的checksum结果为false的情况,可以使用如下方法进行数据修复:
# 下载 mysqldump 工具
# mysql-5.5
wget "https://mysql-documents.s3.cn-north-1.jdcloud-oss.com/mysqldump55" -O ./mysqldump55
# mysql-5.6
wget "https://mysql-documents.s3.cn-north-1.jdcloud-oss.com/mysqldump56" -O ./mysqldump56
# mysql-5.7
wget "https://mysql-documents.s3.cn-north-1.jdcloud-oss.com/mysqldump57" -O ./mysqldump57
# mysql-8.0
wget "https://mysql-documents.s3.cn-north-1.jdcloud-oss.com/mysqldump80" -O ./mysqldump80
# 修复数据
./mysqldump57 -hhost -P3306 -uuser -p'' --set-gtid-purged=OFF database table | mysql -hhost -uuser -p'' -D database
2.4.2 修正Hive 元数据中与HDFS路径相关的信息
2.4.2.1 元数据中与HDFS路径相关的表
经调研,元数据中与HDFS路径相关的信息主要保存在如下元数据表中:
1. DBS
该表存储Hive中所有数据库的基本信息,包括数据库的存储位置
mysql> select * from dbs;
+-------+-----------------------+-------------------------------------------------------------------------------+--------------+------------+------------+
| DB_ID | DESC | DB_LOCATION_URI | NAME | OWNER_NAME | OWNER_TYPE |
+-------+-----------------------+-------------------------------------------------------------------------------+--------------+------------+------------+
| 1 | Default Hive database | HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse | default | public | ROLE |
| 6 | NULL | HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse/user_info_db.db | user_info_db | root | USER |
+-------+-----------------------+-------------------------------------------------------------------------------+--------------+------------+------------+
2 rows in set (0.00 sec)
2. SDS
该表存储文件存储的基本信息:包括表/分区表/分桶表的存放位置
#查询文件的存储信息,此处只展示Location
mysql> select * from SDS;
+------------------------------------------------------------------------------------------------------------------------------------------------+-
| LOCATION |
+------------------------------------------------------------------------------------------------------------------------------------------------+-
| HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse/user_info_db.db/user_tbl_internal |
| HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse/user_info_db.db/user_tbl_ext |
+------------------------------------------------------------------------------------------------------------------------------------------------+-
3. SKEWED_COL_VALUE_LOC_MAP
该表存储表、分区倾斜列对应的文件路径
#查询skewed table的倾斜列的存储路径信息:
mysql> select * from SKEWED_COL_VALUE_LOC_MAP;
+-------+--------------------+---------------------------------------------------------------------------------------------------------------------+
| SD_ID | STRING_LIST_ID_KID | LOCATION |
+-------+--------------------+---------------------------------------------------------------------------------------------------------------------+
| 38 | 11 | HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse/user_info_db.db/user_tbl_ext_skewed_list_bucketing/age=34 |
| 38 | 12 | HDFS://P4anyrQH-Master1.jcloud.local:8020/apps/hive/warehouse/user_info_db.db/user_tbl_ext_skewed_list_bucketing/age=23 |
+-------+--------------------+---------------------------------------------------------------------------------------------------------------------+
4. SERDE_PARAMS
该表存储序列化的一些属性,其KV属性信息PARAM_VALUE中可能会涉及存储路径信息,默认无
5. TABLE_PARAMS
该表存储序列化的一些属性,其KV属性信息PARAM_VALUE中可能会涉及存储路径信息,默认无
2.4.2.2 修正Hive 元数据的方法
元数据修正方式一:人工更新元数据库MySQL表中 HDFS 路径相关内容(推荐)。具体操作为在Hive元数据库所在的MySQL中执行以下SQL语句:
update SDS set location = (select replace(location, '<old path prefix>', '<new path prefix>') ) where location like '%<old path prefix>%';
update DBS set DB_LOCATION_URI = (select replace(DB_LOCATION_URI, '<old path prefix>', '<new path prefix>') ) where DB_LOCATION_URI like '%<old path prefix>%';
update SKEWED_COL_VALUE_LOC_MAP set LOCATION = (select replace(LOCATION, '<old path prefix>', '<new path prefix>') ) where LOCATION like '%<old path prefix>%';
update SERDE_PARAMS set PARAM_VALUE = (select replace(PARAM_VALUE, '<old path prefix>', '<new path prefix>') ) where PARAM_VALUE like '%<old path prefix>%';
update TABLE_PARAMS set PARAM_VALUE = (select replace(PARAM_VALUE, '<old path prefix>', '<new path prefix>') ) where PARAM_VALUE like '%<old path prefix>%';
元数据修正方式二:若是mysqldump出 x.sql 文件,且文件不大,可以使用文本编辑器直接批量替换<old path prefix>为<new path prefix>
元数据修正方式三:使用 hive metatool 更新元数据中 HDFS 路径
参考资料:https://cwiki.apache.org/confluence/display/Hive/Hive+MetaTool
hive --service metatool -updateLocation <new-loc> <old-loc>
#此命令明前只更新DBS/SDS两个表中的HDFS路径相关信息;缺少对表 SKEWED_COL_VALUE_LOC_MAP/SERDE_PARAMS/TABLE_PARAMS 的修改;
适合没有使用 skewed table 倾斜表,并且SERDE_PARAMS/TABLE_PARAMS属性值中无HDFS路径信息的场景;
2.5 迁移验证
2.5.1 基础验证
构造基础查询语句进行验证,例如:
select * from 表名 limit 100;
可以构造这样的一批select 语句存入 sel.sql,进行批量执行,并把结果写入文件result,进行校验:
hive -f sel.sql > result
2.5.2 业务验证
挑选一批业务常用的Hive语句存入test.sql,然后分别在新老集群执行并将结果输出到文件中。
hive -f test.sql > result_src
hive -f test.sql > result_dst
test.sql举例:
[hadoop@P4anyrQH-Master1 ~]$ cat test.sql
use user_info_db;
select * from user_tbl_ext;
select * from user_tbl_internal;
使用diff对比两个hive集群执行结果是否相同:
[root@P4anyrQH-Master1 ~]# diff result_src result_dst -s –normal
文件相同时,diff命令输出:
Files result_src and result_dst are identical
3 Hive迁移测试
3.1 准备测试环境
1、创建两个京东云JMR集群
其中hive和hadoop的版本如下:
hive版本:2.3.7
hadoop版本:2.8.5
2、为Master节点设置环境变量,方便执行hive/hadoop命令
在/etc/profile中文件末尾增加:
export PATH=$PATH:/data0/apache-hive-2.3.7-bin/bin:/data0/hadoop-2.8.5/bin
完成后 source /etc/profile
3、切换到Hadoop用户
su hadoop
3.2 构造常用hive表及数据
3.2.1 准备数据
本地创建文件 user.txt 文本文件
#构造的数据
10,wang,20,jiangsu,xuzhou
11,liu,32,jiangsu,xuzhou
12,ren,34,jiangsu,nanjing
100,cao,34,guangdong,shenzhen
101,li,33,guangdong,shenzhen
102,ma,23,guangdong,guangzhou
1000,cui,12,shan'xi,xi'an
1001,jia,23,shan'xi,xi'an
1002,mi,23,shan'xi,xi'an
1003,ai,23,shan'xi,xi'an
3.2.2 创建Hive库
进入Master节点
#在JMR环境中启动hive
hive
#创建数据库
hive> create database user_info_db;
#使用新创建的数据库
use user_info_db;
3.2.3 创建Hive表并灌入数据
常见的Hive表主要有内部表、普通外部表、外部表、分区表、分桶表、分桶排序表、倾斜表等。以下针对每类表都创建一个表进行迁移测试。
3.2.3.1 内部表
#创建表
create table user_tbl_internal(
uid int,
name string,
age int,
province string,
city string)
row format delimited fields terminated by ','
lines terminated by '\n';
#加载数据
load data local inpath '/root/user.txt' into table user_tbl_internal;
#查看HDFS的文件
hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_internal
3.2.3.2 外部表
#创建一个外表,存储用户信息
create external table user_tbl_ext(
uid int,
name string,
age int,
province string,
city string)
row format delimited fields terminated by ','
lines terminated by '\n';
#加载数据
load data local inpath '/root/user.txt' into table user_tbl_ext;
#查看HDFS的文件
hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext
3.2.3.3 分区表
#分区表的定义:在数据量非常大的时候,为了提升查询效率,节省查询时间,把表数据分散到子目录下的方式就是分区表
#分区表适合的场景和目的:适合对数据量大、有明确合适的分区字段,使用分区字段作为查询条件以提升查询效率。
举例:
#当有海量的数据保存在HDFS某一个hive表名对应的目录下时,使用hive进行操作时,通常会搜索这个目录下所有的文件,会非常耗时;
#如果我们知道这些数据的某些特征,在使用hive进行操作的时候,就可以在where子句中对这些特征进行过滤,那么操作就会在符合条件的子目录下进行,其他不符合条件的目录下的内容就不会被处理。从而提高处理的效率。
#内部表和外部表都可以使用分区的功能,使用分区的内部或外部表称为分区表
#创建一个分区外表,存储用户信息:注意分区字段不能再作为表的一个列名
create external table user_tbl_ext_parti(
uid int,
name string,
age int)
partitioned by(province string, city string)
row format delimited fields terminated by ','
lines terminated by '\n';
#动态导入:
#一般情况在我们都是使用动态分区导入数据
#分区字段有多少个不同的值,就有几个文件。相同分区的数据存放在同一个文件中。
#在导入数据之前必须执行下面的两条语句让hive支持动态分区功能,默认是不支持动态分区的:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
#动态分区导入数据的sql语句:
insert overwrite table user_tbl_ext_parti
partition(province, city)
select uid, name, age, province, city from user_tbl_ext;
#查看数据文件内容
hadoop fs -cat /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=jiangsu/city=xuzhou/000000_0
10,wang,20
11,liu,32
#查看分区表在HDFS中的存放
#多个分区字段,则会有多级目录
[root@P4anyrQH-Master1 bin]# hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/*
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:25 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=guangdong/city=guangzhou
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:25 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=guangdong/city=shenzhen
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:25 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=jiangsu/city=nanjing
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:25 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=jiangsu/city=xuzhou
Found 1 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:25 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=shan%27xi/city=xi%27an
#注意:在使用insert overwrite table #select方式导入数据到分区表时,有多个分区字段时,分区partition中的字段顺序必须和select字段的顺序一致。
补充:也可以使用如下方式进行数据加载,不过需要指定具体的分区字段的值
#加载数据
load data local inpath '/root/user.txt' into table user_tbl_ext_parti partition (provice = "hebei",city = "handan");
3.2.3.4 分桶表
#对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
#适用场景:当数据量比较大,我们需要更快的完成任务,多个map和reduce进程是唯一的选择。但是如果输入文件是一个的话,map任务只能启动一个。此时分桶表是个很好的选择,通过指定CLUSTERED的字段,将文件通过hash打散成多个小文件。
#把表(或者分区)组织成桶(Bucket)有两个好处:
#1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
#2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
#分桶是将某个字段取哈希值,值相同的数据分发到一个桶中;
#在创建分桶表的时候必须指定分桶的字段,并且指定要分桶的数量;
#创建分桶表
create external table user_tbl_ext_parti_bucket(
uid int,
name string,
age int)
partitioned by(province string, city string)
clustered by(age) into 2 buckets
row format delimited fields terminated by ','
lines terminated by '\n';
#设置使用分桶
#插入数据之前需要设置参数hive.enforce.bucketing=true,以强制hive的reducer数目为分桶数。如果不设置这个hive参数,最后的桶个数可能不是建表语句中的个数。
set hive.enforce.bucketing = true;
#导入数据:分区表会以MapReduce任务的方式加载数据
insert overwrite table user_tbl_ext_parti_bucket
partition(province, city)
select uid, name, age, province, city from user_tbl_ext;
#查看分桶表在HDFS中的存放
#多个分区字段,则会有多级目录
hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/*
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:39 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=guangdong/city=guangzhou
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:39 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=guangdong/city=shenzhen
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:39 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=jiangsu/city=nanjing
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:39 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=jiangsu/city=xuzhou
Found 1 items
drwxrwxrwx - hadoop supergroup 0 2021-03-23 20:39 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an
#查看分桶情况:
[hadoop@P4anyrQH-Master1 root]$ hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an
Found 2 items
-rwxrwxrwx 3 hadoop supergroup 12 2021-03-23 21:00 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an/000000_0
-rwxrwxrwx 3 hadoop supergroup 34 2021-03-23 21:00 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an/000001_0
#查看分桶后的文件内容:确实根据分桶值分配到2个桶里了
[hadoop@P4anyrQH-Master1 root]$ hadoop fs -cat /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an/000000_0
1000,cui,12
[hadoop@P4anyrQH-Master1 root]$ hadoop fs -cat /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket/province=shan%27xi/city=xi%27an/000001_0
1003,ai,23
1002,mi,23
1001,jia,23
3.2.3.5 分桶排序表:Bucketed Sorted Tables
分桶排序表形如: CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
#创建分桶排序表
create external table user_tbl_ext_parti_bucket_sort(
uid int,
name string,
age int)
partitioned by(province string, city string)
clustered by(age) sorted by(age) into 2 buckets
row format delimited fields terminated by ','
lines terminated by '\n';
#设置使用分桶
#插入数据之前需要设置参数hive.enforce.bucketing=true,以强制hive的reducer数目为分桶数。如果不设置这个hive参数,最后的桶个数可能不是建表语句中的个数。
set hive.enforce.bucketing = true;
#导入数据:分区表会以MapReduce任务的方式加载数据
insert overwrite table user_tbl_ext_parti_bucket_sort
partition(province, city)
select uid, name, age, province, city from user_tbl_ext;
#查看分桶表在HDFS中的存放
[root@P4anyrQH-Master1 ~]# hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/*
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=guangdong/city=guangzhou
drwxrwxrwx - hadoop supergroup 0 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=guangdong/city=shenzhen
Found 2 items
drwxrwxrwx - hadoop supergroup 0 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=jiangsu/city=nanjing
drwxrwxrwx - hadoop supergroup 0 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=jiangsu/city=xuzhou
Found 1 items
drwxrwxrwx - hadoop supergroup 0 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an
#查看分桶排序表在HDFS中的存放及内容
[root@P4anyrQH-Master1 ~]# hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an/*
-rwxrwxrwx 3 hadoop supergroup 12 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an/000000_0
-rwxrwxrwx 3 hadoop supergroup 34 2021-03-25 12:03 /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an/000001_0
[root@P4anyrQH-Master1 ~]# hadoop fs -cat /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an/000000_0
1000,cui,12
You have mail in /var/spool/mail/root
[root@P4anyrQH-Master1 ~]# hadoop fs -cat /apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti_bucket_sort/province=shan%27xi/city=xi%27an/000001_0
1003,ai,23
1002,mi,23
1001,jia,23
#登录源数据库MySQL查看排序相关信息
mysql -hlocalhost -uhive -p
mysql> use hive;
mysql> select * from SORT_COLS;
+-------+-------------+-------+-------------+
| SD_ID | COLUMN_NAME | ORDER | INTEGER_IDX |
+-------+-------------+-------+-------------+
| 31 | age | 1 | 0 |
| 32 | age | 1 | 0 |
| 33 | age | 1 | 0 |
| 34 | age | 1 | 0 |
| 35 | age | 1 | 0 |
| 36 | age | 1 | 0 |
+-------+-------------+-------+-------------+
6 rows in set (0.00 sec)
3.3 HDFS迁移
3.3.1 迁移HDFS数据
3.3.1.1 全量数据迁移
数据全量迁移:
su hadoop
hadoop distcp -i -log /home/hadoop/logs HDFS://192.168.0.5:8020/apps/hive/warehouse/ HDFS://192.168.0.8:8020/apps/hive/warehouse
3.3.1.2 增量数据迁移
#新增一张表
su hadoop
--创建表
create table user_tbl_add_1(
uid int,
name string,
age int,
province string,
city string)
row format delimited fields terminated by ','
lines terminated by '\n';
--加载数据
load data local inpath '/home/hadoop/user.txt' into table user_tbl_add_1;
--查看HDFS的文件
hadoop fs -ls /apps/hive/warehouse/user_info_db.db/user_tbl_add_1
#原表新增数据
insert into table user_tbl_internal
select uid, name, age, province, city from user_tbl_add_1;
#开始增量迁移
su hadoop
hadoop distcp -i -delete -log /home/hadoop/logs -update HDFS://192.168.0.5:8020/apps/hive/warehouse/ HDFS://192.168.0.8:8020/apps/hive/warehouse
3.3.2 HDFS数据一致性校验
3.3.2.1 校验 HDFS 数据目录文件数量是否一致
#查看源和目标HDFS的目录、文件数、文件内容大小是否相同:
[hadoop@P4anyrQH-Master1 logs]$ hadoop fs -count -v -x /apps/hive/warehouse
DIR_COUNT FILE_COUNT CONTENT_SIZE PATHNAME
36 32 1632 /apps/hive/warehouse
[root@iQotdoaa-Master1 ~]# hadoop fs -count -v -x /apps/hive/warehouse
DIR_COUNT FILE_COUNT CONTENT_SIZE PATHNAME
36 32 1632 /apps/hive/warehouse
经查目录数、文件数、字节数均相同,迁移完成。
3.3.2.2 校验 HDFS 数据目录文件列表是否一致
[hadoop@P4anyrQH-Master1 root]$ hadoop fs -ls -R -C /apps/hive/warehouse
/apps/hive/warehouse/user_info_db.db
/apps/hive/warehouse/user_info_db.db/user_tbl_ext
/apps/hive/warehouse/user_info_db.db/user_tbl_ext/user.txt
/apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti
/apps/hive/warehouse/user_info_db.db/user_tbl_ext_parti/province=guangdong
...
在源集群切换到root用户,执行:hadoop fs -ls -R -C /apps/hive/warehouse > srcfilelist
在目标集群切换到root用户,执行:hadoop fs -ls -R -C /apps/hive/warehouse > dstfilelist
使用diff命令进行比较:
[root@P4anyrQH-Master1 ~]# diff srcfilelist dstfilelist -s --normal
Files srcfilelist and dstfilelist are identical
经查目录和文件列表相同。
3.3.2.3 校验 HDFS 数据目录文件内容是否一致
#查看源端文件MD5值
[hadoop@P4anyrQH-Master1 logs]$ hadoop fs -checksum /apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0
/apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0 MD5-of-0MD5-of-512CRC32C 0000020000000000000000000a59f8a9ab89996e42566969734e21ee
#查看目标端文件MD5值
[root@iQotdoaa-Master1 ~]# hadoop fs -checksum /apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0
/apps/hive/warehouse/user_info_db.db/user_tbl_ext/000000_0 MD5-of-0MD5-of-512CRC32C 0000020000000000000000000a59f8a9ab89996e42566969734e21ee
#MD5值相同表示
经查文件MD5相同,此文件迁移成功。
3.4 Hive元数据迁移
3.4.1 迁移Hive元数据
从源集群导出元数据:mysqldump -hlocalhost -uhive -p --databases hive > hive_bk.sql
导入目标集群:
[root@iQotdoaa-Master1 ~]# mysql -hlocalhost -uhive -p
mysql> source hive_bk.sql
checksum校验数据:
./checksum_table --src-host mysql-xxx.rds.jdcloud.com --src-user 'user-xxx' --src-pass 'password-xxx' --dest-host mysql-xxx.rds.jdcloud.com --dest-user 'user-xxx' --dest-pass 'password-xxx' --ws 30 --database 'dbname-xxx'
3.4.2 修正Hive 元数据中与HDFS路径相关的信息
元数据从源集群迁移到目标集群后,修正元数据中HDFS路径相关信息:
update SDS set location = (select replace(location, 'P4anyrQH-Master1.jcloud.local', 'iQotdoaa-Master1.jcloud.local') ) where location like '%P4anyrQH-Master1.jcloud.local%';
update DBS set DB_LOCATION_URI = (select replace(DB_LOCATION_URI, 'P4anyrQH-Master1.jcloud.local', 'iQotdoaa-Master1.jcloud.local') ) where DB_LOCATION_URI like '%P4anyrQH-Master1.jcloud.local%';
update SKEWED_COL_VALUE_LOC_MAP set LOCATION = (select replace(LOCATION, 'P4anyrQH-Master1.jcloud.local', 'iQotdoaa-Master1.jcloud.local') ) where LOCATION like '%P4anyrQH-Master1.jcloud.local%';
update SERDE_PARAMS set PARAM_VALUE = (select replace(PARAM_VALUE, 'P4anyrQH-Master1.jcloud.local', 'iQotdoaa-Master1.jcloud.local') ) where PARAM_VALUE like '%P4anyrQH-Master1.jcloud.local%';
update TABLE_PARAMS set PARAM_VALUE = (select replace(PARAM_VALUE, 'P4anyrQH-Master1.jcloud.local', 'iQotdoaa-Master1.jcloud.local') ) where PARAM_VALUE like '%P4anyrQH-Master1.jcloud.local%';
3.5 迁移验证
3.5.1 基础验证
修正元数据后可以在目标新集群正常访问hive表数据
hive> select * from user_tbl_ext_parti_bucket;
OK
102 ma 23 guangdong guangzhou
100 cao 34 guangdong shenzhen
101 li 33 guangdong shenzhen
12 ren 34 jiangsu nanjing
11 liu 32 jiangsu xuzhou
10 wang 20 jiangsu xuzhou
1000 cui 12 shan'xi xi'an
1003 ai 23 shan'xi xi'an
1002 mi 23 shan'xi xi'an
1001 jia 23 shan'xi xi'an
Time taken: 0.122 seconds, Fetched: 10 row(s)
hive>
3.5.2 业务验证
构造业务 test.sql并执行。
3.6 构造大量表和海量数据进行迁移测试
有条件的情况下,建议进行大量Hive元数据库表及海量HDFS文件数据迁移的测试验证。