楔子
读
《Hadoop权威指南第三版》
笔记
第15章 关于Sqoop
Hadoop平台的最大优势在于他支持使用不同形式的数据。HDFS能够可靠地存储日志和来自平台不同渠道的其他数据,MapReduce程序能够解析多种数据格式。
为了能够和HDFS之外的数据存储库进行交互,MapReduce程序需要使用外部API来访问数据。通常,一个组织中有价值的数据都存储在关系型数据库系统等结构化存储器中。Sqoop是一个开源工具,它允许用户将数据从结构化存储器抽取到Hadoop中,用于进一步的处理。抽取出的数据可以被MapReduce程序使用,也可被其他类似于Hive的工具使用。(甚至可以使用Sqoop将数据从数据库转移到HBase。)一旦生成最终的分析结果,Sqoop便可以将这些结果导出回数据存储器,供其他客户端使用。
15.1 获取Sqoop
以下我使用的都是sqoop-1.4.5-cdh5.3.6版本
sqoop帮助命令
[grq@hadoop sqoop145]$ bin/sqoop help
Warning: /opt/module/sqoop145/bin/../../hcatalog does not exist! HCatalog jobs will fail.
Please set $HCAT_HOME to the root of your HCatalog installation.
Warning: /opt/module/sqoop145/bin/../../accumulo does not exist! Accumulo imports will fail.
Please set $ACCUMULO_HOME to the root of your Accumulo installation.
18/10/29 22:48:47 INFO sqoop.Sqoop: Running Sqoop version: 1.4.5-cdh5.3.6
usage: sqoop COMMAND [ARGS]
Available commands:
codegen Generate code to interact with database records
create-hive-table Import a table definition into Hive
eval Evaluate a SQL statement and display the results
export Export an HDFS directory to a database table
help List available commands
import Import a table from a database to HDFS
import-all-tables Import tables from a database to HDFS
import-mainframe Import datasets from a mainframe server to HDFS
job Work with saved jobs
list-databases List available databases on a server
list-tables List available tables in a database
merge Merge results of incremental imports
metastore Run a standalone Sqoop metastore
version Display version information
通过将特定工具的名称作为参数,help还能够提供该工具的使用说明。
[grq@hadoop sqoop145]$ bin/sqoop help import
15.2sqoop连接器
Sqoop拥有一个可扩展的框架,使得他能够从(向)任何支持批量数据传输的外部存储系统导入(导出)数据。一个Sqoop连接器就是这个框架下的一个模块化组件,用于支持Sqoop的导入导出操作。Sqoop附带的连接器能够支持大多数常用的关系数据库系统,包括MySQL、PostgreSQL、Oracle、SQL Server和DB2。同时还有一个通用的JDBC连接器,用于支持JDBC协议的数据库。Sqoop所提供的MySQL和PostgreSQL连接器都是经过优化的,通过使用数据库特定的API来提供高效率的批量数据传输。
处理内置的Sqoop连接器外,还有很多针对各种数据存储器的第三方连接器可以使用,能够支持对企业级数据仓库(包括Netezza、Teradata和Oracle)和NoSQL存储器。这些连接器还必须单独下载,它可以根据连接器所附带的安装说明使用添加到已有的Sqoop安装中。
15.3 导入的例子
sqoop-env.sh
配置
export HADOOP_COMMON_HOME=/opt/module/hadoop250
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/opt/module/hadoop250
#set the path to where bin/hbase is available
export HBASE_HOME=/opt/module/hbase0986
#Set the path to where bin/hive is available
export HIVE_HOME=/opt/module/hive013
#Set the path for where zookeper config dir is
export ZOOCFGDIR=/opt/module/zookeeper345/conf
export ZOOKEEPER_HOME=/opt/module/zookeeper345
使用Sqoop导入表到HDFS中
[grq@hadoop sqoop145]$ bin/sqoop import --connect jdbc:mysql://192.168.48.3/life \
--table read_over \
-m 1
导入过程部分执行过程
8/10/30 01:59:19 INFO sqoop.Sqoop: Running Sqoop version: 1.4.5-cdh5.3.6
18/10/30 01:59:19 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
18/10/30 01:59:19 INFO tool.CodeGenTool: Beginning code generation
18/10/30 01:59:21 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `read_over` AS t LIMIT 1
18/10/30 01:59:21 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `read_over` AS t LIMIT 1
18/10/30 01:59:21 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /opt/module/hadoop250
18/10/30 02:00:51 INFO mapreduce.Job: The url to track the job: http://hadoop:8088/proxy/application_1540785517962_0001/
18/10/30 02:00:51 INFO mapreduce.Job: Running job: job_1540785517962_0001
18/10/30 02:02:18 INFO mapreduce.Job: Job job_1540785517962_0001 running in uber mode : false
18/10/30 02:02:18 INFO mapreduce.Job: map 0% reduce 0%
18/10/30 02:02:43 INFO mapreduce.Job: map 100% reduce 0%
18/10/30 02:02:45 INFO mapreduce.Job: Job job_1540785517962_0001 completed successfully
18/10/30 02:02:45 INFO mapreduce.Job: Counters: 30
File System Counters
FILE: Number of bytes read=0
FILE: Number of bytes written=129686
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=87
HDFS: Number of bytes written=150
HDFS: Number of read operations=4
HDFS: Number of large read operations=0
HDFS: Number of write operations=2
Job Counters
Launched map tasks=1
Other local map tasks=1
Total time spent by all maps in occupied slots (ms)=21055
Total time spent by all reduces in occupied slots (ms)=0
Total time spent by all map tasks (ms)=21055
Total vcore-seconds taken by all map tasks=21055
Total megabyte-seconds taken by all map tasks=21560320
Map-Reduce Framework
Map input records=2
Map output records=2
Input split bytes=87
Spilled Records=0
Failed Shuffles=0
Merged Map outputs=0
GC time elapsed (ms)=110
CPU time spent (ms)=1510
Physical memory (bytes) snapshot=97300480
Virtual memory (bytes) snapshot=2064707584
Total committed heap usage (bytes)=30474240
File Input Format Counters
Bytes Read=0
File Output Format Counters
Bytes Written=150
18/10/30 02:02:45 INFO mapreduce.ImportJobBase: Transferred 150 bytes in 158.8214 seconds (0.9445 bytes/sec)
18/10/30 02:02:45 INFO mapreduce.ImportJobBase: Retrieved 2 records.
导入结果查看,因为导入过程中没有指定导入到HDFS的位置,经查找默认导入的位置是/user/${hadoop_user}/${table_name}
[grq@hadoop sqoop145]$ hadoop fs -cat /user/grq/read_over/part-m-00000
18/10/30 02:04:06 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
1,我不过低配的人生,舞满拦江,2018-03-30 01:03:36.0
2,混乱:如何成为失控时代的掌控者,蒂姆·哈福德,2018-04-07 20:47:30.0
[grq@hadoop sqoop145]$
Sqoop的import工具会运行一个MapReduce作业,该作业连接MySQL数据库并读取表中数据,默认情况下,该作业会并行使用4个map任务加加速导入过程。每个任务都将其导入的数据写入到一个单独的文件,但所有4个文件都位于同一个目录中,上述例子中只是使用了一个map任务(-m 1),这样我们只是得到了保存在一个HDFS中的文件
# 上述例子中,我本地测试时由于没有指定 MapReduce任务数量 ,而且我表中数据
#只有2条,打印如下的语句,表示当时只是使用了2个MapReduce。
18/10/30 02:11:45 INFO mapreduce.JobSubmitter: number of splits:2
#找到一张大一点的表,表中数据有10条 测试 MapReduce数量如下
18/10/30 02:16:54 INFO mapreduce.JobSubmitter: number of splits:4
默认执行4个MapReduce程序,结果如下图
默认情况下,Sqoop会将我们导入的数据保存为逗号分隔的文本问价,如果导入的数据库字符内容存在分隔符,我们可以另外指定分隔符、字段包围字符和转义字符。使用命令可以指定分隔符、字段包围符和转义字符
文本和二进制文件格式
Sqoop可以将数据导入成几种不同的格式。文本文件默认(默认)是一种人类可读的数据表示形式,并且是平台独立和最简单的数据格式。但是文本文件不能保存二进制字段(例如数据库中类型为VARBINARY的列),并且在区分null值和字符串null是可能会出现问题(尽管可以使用–null-string选项可以控制空值得表示方式)
为了处理这些情况,用该使用Sqoop的SqeuenceFile格式或者Avro格式。这两种格式文件能够为导入的数据提供最精确的表示方式,同时允许对数据进行压缩。并支持MapReduce并行处理同一文件的不同部分。然而,Sqoop目前的版本还不能将上述格式文件加载到Hive中,SequenceFile文件格式的最后一个缺点是它只支持Java语言。Avro确可以被多种语言处理
15.4 生成代码
除了能够将数据库中内容写入到HDFS,Sqoop同时还生成了一个Java源文件,保存在当前脚本的本地目录中。(如上图)
Sqoop在将源数据库的表数据写到HDFS之前,会首先用生成的代码对其进行反序列化。
生成代码read_over的java文件
15.6 使用导入的数据
数据被导入HDFS,就可以供定制的MapReduce程序使用。导入的文本格式可以供Hadoop Streaming的脚本或以TextInputFormat为默认格式运行的MapReduce作业使用
导入的数据与Hive
对于很多类型的分析认为来说,使用类似于Hive的系统来处理关系操作有利于加快分析任务的开发。对于关系数据源的数据,使用hive是非常有帮助的。Hive和Sqoop共同构成了一个强大的服务分析任务的工具类链。
下面命令是生成一个Hive表的定义。
[grq@hadoop sqoop145]$ bin/sqoop create-hive-table --connect jdbc:mysql://192.168.48.3/life \
> --table kidnel_need_read --fields-terminated-by '\t'
Wa
## 然后使用 hive 的load命令加载数据到Hive表中
如果想直接从数据库将数据导入到Hive。可以将上述的三个步骤(将数据导入HDFS;创建Hive表;将HDFS中数据导入Hive
)缩短为一个步骤。在导入时,Sqoop可以生成Hive表的定义,根据MySQL中数据直接创建Hive中的表:
使用–hive-import 参数运行sqoop import工具,可以从源数据库直接将数据导入hive中
[grq@hadoop sqoop145]$ bin/sqoop import --connect jdbc:mysql://192.168.48.3/life --table kidnel_need_read -m 1 --hive-import
导入后情况
[grq@hadoop sqoop145]$ bin/sqoop import --connect jdbc:mysql://192.168.48.3/life --table kidnel_need_read -m 1 --hive-import --fields-terminated-by "\t"
导入情况
上述为空是因为Hive和Sqoop默认的字符分隔符不一致,Sqoop默认是逗号,hive使用的是"\t" ,在导入时还有数据库的用户名和密码,我数据库没密码,所以参数没设置(–username root
–password 123456 )
15.7 导入大对象
很多数据库都支持在一个字段中保存大量的数据,数据是根据是文本还是二进制类型,通常保存在CLOB和BLOB类型中。数据库一般会会对这些“大对象”进行特殊处理。
未完待续
15.8 执行导出
在Sqoop中,导出(export)是将HDFS作为数据源,讲一个远程数据库作为目标。前面将导入数据使用Hive对数据进行分析。可以将分析结果导出到一个数据库中,供其他工具使用。
将一张表从HDFA导出到数据库时,必须在数据库中创建一张用于接收数据的目标表。虽然Sqoop可以推断出那个JAVA类型是和存储SQL数据类型,但是反过来确是行不通的,因此,必须由用户确定哪些类型是最合适的。
从Hive导出表先要在MySQL中创建表
使用上述导入的表重新创建一个新表,两个表结构一样
[grq@hadoop sqoop145]$ bin/sqoop export --connect jdbc:mysql://192.168.48.3:3306/life -m 1 --export-dir /user/hive/warehouse/kidnel_need_read --input-fields-terminated-by '\t' \
> --table hive_book