使用Sqoop将Mysql数据导入Hive踩坑

本文详述从Mysql数据库向Hive进行数据迁移的过程,包括遇到的问题及解决策略,如数据类型转换、特殊字符处理、空值处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:
由于公司这个项目存在阿里云上,不能由DBA来维护,所以想要把数据从Mysql抽取到Hive上就需要我们自己来动手。。。
数据量不是很大,但是分了巨多的库;需要导入的只有7张表,但是大概有94个库,每个库下边都有这七张表。
初步设计方案是在把Mysql不同数据库的数据存放在Hive表不同的分区,就是一张hive表大概有90多个分区。

最初想法:
1.先用sqoop复制表结构;
2.循环数据库添加分区并向分区中导入数据。
命令:
##sqoop复制表结构
sqoop create-hive-table
-D mapred.job.queue.name=root.line.ploan
–connect jdbc:mysql://host:host:host:port/$database
–username $user
–password $password
–table $tablename
–hive-database $hive_database
–hive-table $tablename
–hive-partition-key db
–fields-terminated-by “\t”
–lines-terminated-by “\n”

##Hive添加分区
hive -e ’
use sirrus;
elter table tablenameaddpartition(db=′tablename add partition(db='tablenameaddpartition(db=database’);
exit;

##向分区插入数据
sqoop import
-D mapred.job.queue.name=root.line.ploan \ ##设置MR执行队列
–connect jdbc:mysql://host:host:host:port/$database \ ##设置Mysql连接
–username $user \ ##设置Mysql登陆用户
–password $password \ ##设置Mysq登陆l密码
–table $tablename \ ##要导入HIVE的Mysql表名
–fields-terminated-by “\t” \ ##导入HDFS后的列分割符
–delete-target-dir \ ##如果目标目录已存在,则先删除
–hive-import \ ##指定导入到Hive中
–m 1 \ ##设定启动Mapper个数
–hive-partition-key db \ ##指定导入Hive的分区字段
–hive-partition-value $database \ ##指定导入Hive的哪个分区
–hive-database sirrus \ ##指定导入Hive表所在的库
–hive-table $tablename ##指定要导入的Hive表

问题:

再看发生的问题之前大家先看一段代码:

##Hive处理数据库类型的方法
public static String toHiveType(int sqlType) {

 switch (sqlType) {  
     case Types.INTEGER:  
     case Types.SMALLINT:  
         return "INT";  
     case Types.VARCHAR:  
     case Types.CHAR:  
     case Types.LONGVARCHAR:  
     case Types.NVARCHAR:  
     case Types.NCHAR:  
     case Types.LONGNVARCHAR:  
     case Types.DATE:  
     case Types.TIME:  
     case Types.TIMESTAMP:  
     case Types.CLOB:  
         return "STRING";  
     case Types.NUMERIC:  
     case Types.DECIMAL:  
     case Types.FLOAT:  
     case Types.DOUBLE:  
     case Types.REAL:  
         return "DOUBLE";  
     case Types.BIT:  
     case Types.BOOLEAN:  
         return "BOOLEAN";  
     case Types.TINYINT:  
         return "TINYINT";  
     case Types.BIGINT:  
         return "BIGINT";  
     default:  
   // TODO(aaron): Support BINARY, VARBINARY, LONGVARBINARY, DISTINCT,  
   // BLOB, ARRAY, STRUCT, REF, JAVA_OBJECT.  
   return null;  
 }  

}

1.直接运行上面sqoop命令,查询,失败。。。。(类型自动转化) sqoop复制的Mysql表结构到HIVE,发现部分字段类型发生了变化;

tinyint(1) -> boolean
decimal -> double
datetime -> string 等

由上面代码可以知道,hive将Mysql中的数据类型进行了转化:
integer、smallint -> int
varchar、char、longvarchar、nvarchar、nchar、longnvarchar、date、time、timestamp、clob -> string;
numeric、decimal、float、double、real -> double;
bit、boolean -> boolean;
tinyint -> tinyint;
bigint -> bigint.
如果包含decimal数据类型可能会失精度,所以不建议使用sqoop自动创建Hive表(如果包含上面几种字段的话)

2.先在Hive按照Mysql字段类型创建好表,不自动建表,执行,数据导完,查询(tinyint(1)为boolean类型)
发现有列是null。。。什么鬼,排查发现这几列是tinyint(1)类型,明明是tinyint啊,hive上也是tinyint啊,怎么肥四??
查阅资料发现
MySQL保存boolean值时用1代表TRUE,0代表FALSE。boolean在mysql里的类型为tinyint(1)。

果然书到用时方恨少。。
两种解决方案:
将 --connect jdbc:mysql://host:host:host:port/database修改为−−connectjdbc:mysql://database修改为--connect jdbc:mysql://databaseconnectjdbc:mysql://host:port/port/port/database?tinyInt1isBit=false
–map-column-hive ${列名}=tinyint
3.特殊字符处理
这下总可以了吧,修改好继续执行,检查又发现一个表里莫名其妙多出一条数据,而且有的列没有数据。。。
原因:
设置的Hive列分割符为 \t,行分割符为\n,而mysql中有一条数据存在 \t,\n
解决方案:
设置hive列分割符为\001,但是行分割符仅支持\n,所以需要添加
–hive-drop-import-delims \ ##处理特殊字符

4.导到最后一张表的时候突然抱错(不支持类型处理)。
ERROR org.apache.sqoop.tool.ImportTool: Encountered IOException running import job: java.io.IOException: [color=darkred]Hive does not support the SQL type for column VARBINARY[/color]
比较简单,从上面的java代码就知道了:
HIVE做类型转换的时候,没有写VARBINARY类型的处理
只需做一下映射即可
解决方案:
–map-column-hive ${列名}=STRING

5.Hive空值处理
终于ok,555.。。。hive查询验证一下所有表,完美没问题
impala查询测试。结果正确。但是报错。。。

Error converting column: 12 to DECIMAL(10,2)
Error converting column: 13 to TIMESTAMP

查询hdfs文件发现,对应列的位置存储的是 NULL 字符串。但是字段类型为decimal和timestamp不匹配所以显示null,不能显示NULL字符串,虽然结果正确,数据却是不正确的。
解决方案:对Hive进行空值处理
–null-string ‘\N’
–null-non-string ‘\N’ \
记住是’\N’ . 不是’\N’ 原因应该都知道。

重新导入,终于DONE。。。

在 DolphinScheduler 中使用 SqoopMySQL 导入数据Hive,通常涉及 Sqoop 脚本的编写、Hive 和 Hadoop 环境的配置、以及 DolphinScheduler 的任务调度配置。以下是具体实现方法和注意事项。 ### 1. Sqoop 命令的编写 Sqoop 用于将 MySQL 数据导入 Hive 的基本命令如下: ```bash sqoop import \ --connect jdbc:mysql://<mysql-host>:3306/<database-name> \ --username <mysql-username> \ --password <mysql-password> \ --table <table-name> \ --hive-import \ --hive-table <hive-database>.<hive-table-name> \ --hive-overwrite \ --fields-terminated-by ',' \ --lines-terminated-by '\n' \ --target-dir /user/hive/warehouse/<hive-database>.db/<hive-table-name> ``` 其中: - `--connect` 指定 MySQL 数据库的连接地址。 - `--username` 和 `--password` 用于数据库认证。 - `--table` 指定 MySQL 中的源表。 - `--hive-import` 表示将数据导入Hive。 - `--hive-table` 指定 Hive 中的目标表。 - `--hive-overwrite` 允许覆盖目标表中的现有数据。 - `--fields-terminated-by` 和 `--lines-terminated-by` 定义文件中的字段和行分隔符。 - `--target-dir` 指定 HDFS 中的存储路径,Hive 会从此路径读取数据。 ### 2. DolphinScheduler 中的任务配置 在 DolphinScheduler 中,可以通过 Shell 任务或 Sqoop 任务类型执行 Sqoop 命令。具体步骤如下: 1. **创建工作流**:进入 DolphinScheduler Web UI,创建一个新的工作流。 2. **添加任务节点**:选择任务类型为 `Shell` 或 `Sqoop`(如果支持)。 3. **编写脚本**:在任务的脚本编辑器中输入上述 Sqoop 命令。 4. **配置资源**:确保任务节点中引用了正确的资源文件(如配置文件或脚本文件)。 5. **设置调度时间**:根据需求配置调度策略,例如一次性执行或周期性执行。 6. **保存并上线**:完成配置后保存并上线工作流。 ### 3. 环境配置与问题处理 #### 3.1 Hive 依赖问题 在 DolphinScheduler 中运行 Sqoop 任务时,可能会遇到类路径问题,例如 `NoClassDefFoundError` 或 `ClassNotFoundException`。解决方法包括: - 确保所有 Hive 和 Hadoop 的依赖库(如 `hive-metastore` 和 `hadoop-client`)已正确安装并配置。 - 在 DolphinScheduler 的环境变量中设置 `HADOOP_CLASSPATH`,以包含 HiveSqoop 的依赖库。 #### 3.2 Hadoop 配置 确保 Hadoop 的配置文件(如 `core-site.xml` 和 `hdfs-site.xml`)位于 Sqoop 的类路径中。可以通过设置 `HADOOP_CONF_DIR` 环境变量实现: ```bash export HADOOP_CONF_DIR=/opt/installs/hadoop/etc/hadoop ``` #### 3.3 DolphinScheduler 配置 如果 DolphinScheduler 运行在腾讯云等特殊环境中,可能会遇到 `UnknownHostException` 或 `NullPointerException`。需要检查并修改 DolphinScheduler 的配置文件 `common.properties`,确保以下配置正确: ```properties resource.manager.httpaddress.port=5004 ``` ### 4. 数据导入流程示例 假设 MySQL 中有一个表 `employees`,需要导入Hive 中的 `default.employees` 表中,具体步骤如下: 1. **创建 Hive 表**:在 Hive 中提前创建目标表。 ```sql CREATE TABLE default.employees ( id INT, name STRING, department STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'; ``` 2. **执行 Sqoop 命令**:使用 DolphinScheduler 调度 Sqoop 命令将数据导入 Hive。 ```bash sqoop import \ --connect jdbc:mysql://localhost:3306/company_db \ --username root \ --password password \ --table employees \ --hive-import \ --hive-table default.employees \ --hive-overwrite \ --fields-terminated-by ',' \ --lines-terminated-by '\n' \ --target-dir /user/hive/warehouse/default.db/employees ``` 3. **验证数据**:在 Hive 中查询导入数据,确保数据已正确加载。 ```sql SELECT * FROM default.employees; ``` ### 5. 常见问题与解决方案 #### 5.1 NoClassDefFoundError 如果出现 `NoClassDefFoundError` 错误,通常是由于缺少 Hive 或 Hadoop 的依赖库。解决方法包括: - 确保所有必要的 JAR 文件已正确安装。 - 在 Sqoop 命令中使用 `--libjars` 参数指定依赖库的路径。 #### 5.2 UnknownHostException 如果 DolphinScheduler 报 `UnknownHostException`,可能是由于 ResourceManager 的 HTTP 地址配置错误。解决方法包括: - 修改 DolphinScheduler 的 `common.properties` 文件,设置正确的 HTTP 端口。 #### 5.3 NullPointerException 如果 DolphinScheduler 报 `NullPointerException`,可能是由于任务状态获取失败。解决方法包括: - 检查 DolphinScheduler 的日志,确认是否与 ResourceManager 的连接有关。 - 确保 ResourceManager 的 HTTP 地址和端口配置正确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值