sqoop学习之路

前言

sqoop是一款用于结合关系型数据库和hdfs(hive/hbase)的数据库之间数据相互传递的工具,可以将mysql/oracle等数据库中存在的表通过sqoop来传递给hive或着是hbase,同样也可以将hive或者是hbase中的表格传递给sqoop中,非常好用。此博客介绍sqoop的版本为1.4.6,主要涉及安装和使用:

  • sqoop作用

    1. hadoop大数据存储平台:hdfs、hive、hbase
    2. rdbms关系型数据库 : mysql、oracle、postgresql
    3. 迁入:关系型数据库到大数据平台 import
    4. 迁出:大数据平台到关系型数据库 export
    5. 本质:sqoop将数据迁移命令转化为MR,只需在一个节点安装(sqoop底层只需要重新定义输入inputformat 输出outputformat)
  • sqoop原理
    把用户的指令解析编译成MR任务,发布到yarn上分布式执行
    MR任务把输入和输出分别对接RDBMS和Hadoop就能完成数据的转移

  • sqoop版本

sqoop1:
	1. 核心组件:TaskTranslator,解析编译用户指令,生成mr任务发布到yarn
	2. cli、api :和用户交互,从用户接受命令,把命令发送给TaskTranslator
	3. 优点:简单、灵活、易用,不需要做什么配置,指令即配置,指令可以马上执行
	4. 缺点:支持shell和java等语言,对于其他语言无法支持

sqoop2
	1. server端:
		a)核心组件:TaskTranslator,解析编译用户指令,生成mr任务发布到yarn
		b)Connector连接存储系统的中间组件
		c)Metadata:
			1)存储用户跟存储系统的连接信息:link
			2)存储数据导入导出的指令信息:Job
		d)RestServer:
			1)对外接受客户端的服务
			2)接受客户端的连接,接受客户端的指令,把指令发送给TaskTranslator
		e)UiServer:对外接受客户端的服务
	2. client端:cli、api、webui
	3. 优点:
		a)通用更强
		b)会记录元数据包括存储系统连接信息和任务配置信息等
	4. 缺点:
		a)步骤稍显麻烦
		b)对记录的连接需要使用Connector来连接

一、sqoop的安装

和sqoop一起工作的组件:
mysql(传统关系型数据库 )、hdfs(集群)、hive(安装在一个节点)、hbase(集群)、zookeeper

1. 下载 sqoop-1.4.6
2. 上次Linux,解压sqoop-1.4.6
	[hadoop@hadoop01 ~]$  tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
3. 设置环境变量
	[hadoop@node1 ~]$  sudo vi /etc/profile
		(以下是我的配置文件,仅供参考,你也可以在家目录下修改 .bash_profile文件,此文件也可以作为用户配置文件)
		export JAVA_HOME=/home/hadoop/jdk1.7.0_67
		export HADOOP_HOME=/home/hadoop/hadoop-2.7.1
		export ZK_HOME=/home/hadoop/zookeeper-3.4.6
		export HIVE_HOME=/home/hadoop/apache-hive-1.2.1-bin
		export HBASE_HOME=/home/hadoop/hbase-1.1.2
		export SQOOP_HOME=/home/hadoop/sqoop-1.4.6.bin__hadoop-2.0.4-alpha
		export PATH=$PATH:${JAVA_HOME}/bin:${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:${ZK_HOME}/bin:${HIVE_HOME}/bin:${HBASE_HOME}/bin:${SQOOP_HOME}/bin
4. 验证sqoop安装是否成功
	[hadoop@node1 ~]$  sqoop help
		(输出结果)
		Warning: /home/hadoop/apps/sqoop-1.4.6/../hcatalog does not exist! HCatalog jobs will fail.
		Please set $HCAT_HOME to the root of your HCatalog installation.
		Warning: /home/hadoop/apps/sqoop-1.4.6/../accumulo does not exist! Accumulo imports will fail.
		Please set $ACCUMULO_HOME to the root of your Accumulo installation.
		18/12/18 02:51:27 INFO sqoop.Sqoop: Running Sqoop version: 1.4.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

		See 'sqoop help COMMAND' for information on a specific command.
5. 设置 sqoop-1.4.6/conf 目录下配置文件
	[hadoop@node1 ~]$  cp sqoop-env-template.sh sqoop-env.sh
	[hadoop@node1 ~]$  vim sqoop-env.sh
		(以下是我的配置文件,仅供参考)
		#Set path to where bin/hadoop is available
		export HADOOP_COMMON_HOME=/home/hadoop/apps/hadoop-2.7.6
		#Set path to where hadoop-*-core.jar is available
		export HADOOP_MAPRED_HOME=/home/hadoop/apps/hadoop-2.7.6
		#set the path to where bin/hbase is available
		export HBASE_HOME=/home/hadoop/apps/hbase-1.2.6
		#Set the path to where bin/hive is available
		export HIVE_HOME=/home/hadoop/apps/apache-hive-2.3.2-bin
		#Set the path for where zookeper config dir is
		export ZOOCFGDIR=/home/hadoop/apps/zookeeper-3.4.10/conf
	[hadoop@node1 ~]$  vim sqoop-site.xml
		(不进行配置)
6. 复制需要的 jar 包到目录 sqoop-1.4.6/lib 下 
	(以下命令参考)
	[hadoop@node1 ~]$  cp $HADOOP_HOME/share/hadoop/common/hadoop-common-2.7.6.jar $SQOOP_HOME/lib
	拷贝mysql的驱动包到sqoop的lib下:
	[hadoop@node1 ~]$  cp mysql-connector-java-5.1.37-bin.jar $SQOOP_HOME/lib
	注意:mysql-connector-java-5.1.37-bin.jar这个包很有用
7.  验证:
	sqoop list-databases \
	--connect jdbc:mysql://localhost:3306/ \
	--username root \
	--password root

二、sqoop的使用

  1. sqoop help
    在linux中输入sqoop help:
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

See 'sqoop help COMMAND' for information on a specific command.

翻译:

codegen            		生成java代码  pojo
create-hive-table  		导入数据到hive表中
eval               
export             		导出
help               
import             		导入   关系型数据库----大数据平台
import-all-tables  		将库下的所有的表导入hdfs
import-mainframe   		Import datasets from a mainframe server to HDFS
job                		Work with saved jobs
list-databases     		显示所有数据库
list-tables        		显示所有表
merge              		Merge results of incremental imports
metastore          		Run a standalone Sqoop metastore
version            		版本信息

导入:
--connect				指定数据库链接url
--username				指定数据库的用户名
--password				指定数据库的密码
--table					指定要导出数据的mysql数据库表
-m						指定MapTask的个数
--target-dir			指定导出数据在HDFS上的存储目录
--fields-terminated-by	指定每条记录中字段之间的分隔符
--where					指定查询SQL的where条件
--query					指定查询SQL
--columns				指定查询列
  1. 功能
一、sqoop数据导入:
	help_keyword
	--connect  		mysql连接url
	--driver  		驱动  (不需要指定)
	--username   	mysql的用户名
	--password    	mysql的密码
	-m  			maptask的并行度

1) mysql  导入  hdfs   
	a) --table  用于指定mysql中的表
		sqoop import \
		--connect jdbc:mysql://localhost:3306/mysql \		mysql连接url
		--username root \								mysql的用户名
		--password 123456 \								mysql的密码
		--table help_keyword \							指定mysql中的表
		-m 2											maptask的并行度
		(默认路径:/user/hive/warehouse;默认的分割符:)
	b) --fields-terminated-by:指定分割符    --target-dir:指定存储路径
		sqoop import \
		--connect jdbc:mysql://localhost:3306/mysql \
		--username root \
		--password 123456 \
		--target-dir hdfs://bd1804/sqoop/target \			指定路径
		--fields-terminated-by '\t' \					指定分隔符
		--table help_keyword \
		-m 2
	c) 导出过滤条件的:select ....from....where:指定过滤条件
		sqoop import \
		--connect jdbc:mysql://localhost:3306/mysql \
		--username root \
		--password 123456 \
		--where "name='JOIN'" \							where 指定过滤条件
		--target-dir hdfs://bd1804/sqoop/target00 \
		--fields-terminated-by '\t' \
		--table help_keyword \							table 指定表
		-m 2
	d) sql语句进行导入:-e  --query指定sql语句   --split-by指定maptask的切分字段
		sqoop import   \
		--connect jdbc:mysql://localhost:3306/mysql  \
		--username root  \
		--password 123456   \
		--target-dir hdfs://bd1804/sqoop/target01  \
		--query "select help_keyword_id,name from help_keyword where \$CONDITIONS and name = 'JOIN'" \			指定sql语句
		--split-by  help_keyword_id \					指定maptask切分字段
		--fields-terminated-by '\t'  \					指定分隔符
		-m 4
		(注意:1. where过滤条件后面必须跟$CONDITIONS
		  	  2. 单引号$CONDITIONS  不需要转义   “”  $需要转义
		  	  3. --query和--table不可以同时使用
		另,注意点:1.--split-by对非数字类型的字段支持不好。一般用于主键
		及数字类型的字段。假设有一张表test,sqoop命令中--split-by 'id',
		-m 10,会发生怎样奇特的事情。首先呢,sqoop会去查表的元数据等等,
		重点说一下sqoop是如何根据--split-by进行分区的。首先sqoop会向关系
		型数据库比如mysql发送一个命令:select max(id),min(id) from test。
		然后会把max、min之间的区间平均分为10分,最后10个并行的map去找数据
		库,导数据就正式开始啦!

)
	e) --where 和 --columns 一起使用,指定字段导入
		sqoop import   \
		--connect jdbc:mysql://localhost:3306/mysql   \
		--username root  \
		--password 123456   \
		--columns "name" \								指定字段导入
		--where "name='JOIN'" \
		--table help_keyword  \
		--target-dir hdfs://bd1804/sqoop/target03 \
		-m 3
2) mql  导入  hive
	(注意:Sqoop 导入关系型数据到 hive 的过程是先
	导入到 hdfs,然后再 load 进入 hive)
	a) 普通导入
		示例1:
		sqoop import \
		--connect jdbc:mysql://hadoop02:3306/mysql \
		--username root \
		--password root \
		--table help_keyword \
		--hive-import \
		-m 1
		(注意:导入数据到 hive 表,默认表在 default 库下,表名一样,采用'\u0001'分隔)
		示例2:
		sqoop import \
		--connect jdbc:mysql://hadoop02:3306/mysql \
		--username root \
		--password root \
		--table help_keyword \
		--fields-terminated-by "\t" \
		--lines-terminated-by "\n" \
		--hive-import \
		--hive-overwrite \
		--create-hive-table \
		--hive-table mydb_test.new_help_keyword \
		--delete-target-dir
		(注意:表会自动创建,但是库不会。所以在执行该语句之前,
		一定要确保 hive 的数据库mydb_test 是存在的,否则程序会报错)
	b)增量导入
		(增量导入是仅导入表中新添加的行的技术。它需要添加 'incremental',
		'check-column', 和 'last-value' 选项来执行增量导入。下面的语法
		结构用于 Sqoop 导入命令增量选项。)
		示例:
		sqoop import \
		--connect jdbc:mysql://hadoop02:3306/mysql \
		--username root \
		--password root \
		--table help_keyword \
		--target-dir /user/hadoop/myimport3 \
		--incremental append \							指定增量导入
		--check-column help_keyword_id \					指定检查字段
		--last-value 500 \								增量导入的条件
		-m 1
		(此处结果不包含 help_keyword_id = 500 数据,数据是大于 500 的)
3)mysql  导入  hbase
	示例:
	sqoop import \
	--connect jdbc:mysql://hadoop02:3306/mysql \
	--username root \
	--password root \
	--table help_keyword \
	--hbase-table new_help_keyword \
	--column-family person \
	--hbase-row-key h
	字段解释:
	--connect jdbc:mysql://hadoop04:3306/mysql 		表示远程或者本地 Mysql 服务的 URI
	--hbase-create-table 							表示在 HBase 中建立表。
	--hbase-table new_help_keyword 					表示在 HBase 中建立表 new_help_keyword。
	--hbase-row-key help_keyword_id 					表示hbase表的rowkey是mysql表的help_keyword_id 字段
	--column-family person 							表示在表 new_help_keyword 中建立列族 person。
	--username 'root' 								表示使用用户 root 连接 mysql。	
	--password 'root' 								连接 mysql 的用户密码
	--table help_keyword 							表示导出 mysql 数据库的 help_keyword 表。


二、数据导出
1) hdfs  导入  mysql
	Export 常用参数:
		--direct 快速导入
		--export-dir  			HDFS 到处数据的目录
		-m,--num-mappers  		都少个 map 线程
		--table  				导出哪个表
		--call  				存储过程
		--update-key  			通过哪个字段来判断更新
		--update-mode 			插入模式,默认是只更新,可以设置为 allowinsert.
		--input-null-string 		字符类型 null 处理
		--input-null-non-string 	非字符类型 null 处理
		--staging-table 			临时表
		--clear-staging-table 	清空临时表
		--batch 				批量模式
	步骤:
	第一步:查看要导入mysql的数据:hadoop  dfs  -tail  文件名
	第二步:在mysql表中建表
	第三步:执行导出命令
		示例:
		sqoop export \
		--connect jdbc:mysql://hadoop02:3306/sqoopdb \
		--username root \
		--password root \
		--table sqoopstudent \
		--export-dir /sqoopdata \
		--fields-terminated-by ','
		(注意:如果导出数据到 mysql 出现乱码,那么请参考这个解决方案:
		https://my.oschina.net/u/559635/blog/498990)
2) hive  导入  mysql
	sqoop export \
	--connect jdbc:mysql://hadoop02:3306/sqoopdb \
	--username root \
	--password root \
	--table uv_info \
	--export-dir /user/hive/warehouse/uv/dt=2011-08-03 \
	--input-fields-terminated-by '\t
	(注意:其实跟直接导出 HDFS 数据到 MySQL 没什么两样)
3) Hbase  导入  mysql
	很遗憾,现在还没有直接的命令将 HBase 的数据导出到 MySQL,一般采用如下 3 种方法:
		1、将 Hbase 数据,扁平化成 HDFS 文件,然后再由 sqoop 导入
		2、将 Hbase 数据导入 Hive 表中,然后再导入 mysql
		3、直接使用 Hbase 的 Java API 读取表数据,直接向 mysql 导入,不需要使用 sqoop
	
  1. 原理解析

1)sqoop导入原理

我们能得出一个结论,sqoop 工具是通过 MapReduce 进行导入作业的,sqoop进行数据导入流程大致可以用下面文字描述:
	1、第一步,Sqoop 会通过 JDBC 来获取所需要的数据库元数据,例如,导入表的列名,数据类型等。
	2、第二步,这些数据库的数据类型(varchar, number 等)会被映射成 Java 的数据类型(String, int等),根据这些信息,Sqoop 会生成一个与表名同名的类用来完成序列化工作,保存表中的 Stay hungry Stay foolish -- http://blog.csdn.net/zhongqi2513每一行记录。
	3、第三步,Sqoop 启动 MapReducer 作业
	4、第四步,启动的作业在 input 的过程中,会通过 JDBC 读取数据表中的内容,这时,会使用 Sqoop 生成的类进行反序列化操作
	5、第五步,最后将这些记录写到 HDFS 中,在写入到 HDFS 的过程中,同样会使用 Sqoop 生成的类进行反序列化

2)sqoop导出原理

Sqoop 进行数据导出,总体也是基于 mapreduce 任务。也可以描述为以下5步:
	1、第一步,sqoop 依然会通过 JDBC 访问关系型数据库,得到需要导出数据的元数据信息
	2、第二步,根据获取到的元数据的信息,sqoop 生成一个 Java 类,用来进行数据的传输载体。该类必须实现序列化和反序列化
	3、第三步,启动 mapreduce 作业
	4、第四步,sqoop 利用生成的这个 java 类,并行的从 hdfs 中读取数据
	5、第五步,每个 map 作业都会根据读取到的导出表的元数据信息和读取到的数据,生成一批 insert 语句,然后多个 map 作业会并行的向数据库 mysql 中插入数据
	(注意:所以,数据是从 hdfs 中并行的进行读取,也是并行的进入写入,那并行的读取是依赖 hdfs的性能,而并行的写入到 mysql 中,那就要依赖于 mysql 的写入性能了。)

附录

1)import的主要参数
	--connect     						jdbc连接地址
	--connection-manager      		连接管理者
	--driver      					驱动类
	--hadoop-mapred-home      				$HADOOP_MAPRED_HOME
	--help    									help信息
	-P     										从命令行输入密码
	--password      					密码
	--username      					账号
	--verbose    								打印信息
	--connection-param-file   			可选参数

	Argument :     								Description :
	--append     								添加到hdfs中已经存在的dataset
	--as-avrodatafile     						导入数据作为avrodata
	--as-sequencefile    		 				导入数据位SequenceFiles
	--as-textfile          						默认导入数据为文本
	--boundary-query      			创建splits的边界
	--columns      				选择列
	--direct             						使用直接导入快速路径
	--direct-split-size      					在快速模式下每n字节使用一个split
	--fetch-size      						一次读入的数量
	--inline-lob-limit      					最大数值 an inline LOB
	-m,--num-mappers      					通过实行多少个map,默认是4个,某些数据库8 or 16性能不错
	-e,--query      					通过查询语句导入
	--split-by      				创建split的列,默认是主键
	--table      					要导入的表名
	--target-dir      						HDFS 目标路径
	--warehouse-dir      					HDFS parent for table destination
	--where      					where条件
	-z,--compress     							Enable compression
	--compression-codec      					压缩方式,默认是gzip
	--null-string     				字符列null值
	--null-non-string      			非字符列null值

2)export主要参数
	--direct     								快速导入
		--export-dir      					HDFS到处数据的目录
	-m,--num-mappers      					都少个map线程
	--table      					导出哪个表
	--call      				存储过程
	--update-key      					通过哪个字段来判断更新
	--update-mode      					插入模式,默认是只更新,可以设置为allowinsert.
	--input-null-string      		字符类型null处理
	--input-null-non-string      	非字符类型null处理
	--staging-table      		临时表
	--clear-staging-table                     	清空临时表
	--batch                                     	批量模式


3)转义字符相关参数。
	Argument :     								Description :
	--enclosed-by      					设置字段结束符号
	--escaped-by      						用哪个字符来转义
	--fields-terminated-by      			字段之间的分隔符
	--lines-terminated-by      			行分隔符
	--mysql-delimiters             				使用mysql的默认分隔符: , lines: \n escaped-by: \ optionally-enclosed-by: '
	--op

实战

1. pg库导入hive
	#!/bin/bash
	source /etc/profile
	source ./bash_profile
	
	#connection info
	#数据库ip
	ip=10.20.129.20
	#数据库port
	port=1234
	#数据库名称
	db=dbname
	#DB账号
	username=username
	#密码
	password=password
	
	#pg数据库表名
	src_table=tablename
	#hive表数据库
	tar_db=spark_graphx
	#hives表表名
	tar_table=tablename
	#pg_connect
	connect=jdbc:postgresql://$ip:$port/$db
	
	echo "*******************run sqoop********************"
	sqoop  import "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" \
	--connect  $connect \
	--username  $username \
	--password  $password \
	--query  "select * from $table where \$CONDITIONS" \    #一定要加上  where  \$CONDITIONS
	--delete-target-dir \
	--hive-database  $tar_db \
	--hive-table $tar_table \
	--hive-import \
	--target -dir /input/$tar_table \      #可以省略,为默认路径
	-m  10 \
	--split-by id
2. hive导入pg数据库
	#!/bin/bash
	source /etc/profile
	source ./bash_profile
	
	#connection info
	#数据库ip
	ip=10.20.129.20
	#数据库port
	port=1234
	#数据库名称
	db=dbname
	#DB账号
	username=username
	#密码
	password=password
	
	#pg数据库表名
	tar_table=tablename
	#hive表数据库
	src_db=spark_graphx
	#hives表表名
	src_table=tablename
	#pg_connect
	connect=jdbc:postgresql://$ip:$port/$db
	hdfspath=hdfs://aicrs/user/hive/warehouse
	hive_dbname=spark_graphx
	
	echo  "**********************想  pg  导入数据*****************************"
	sqoop export \
	--connect  $connect \
	--username  $username \
	--password  $password \
	--table  $tar_table \
	--export-dir  $hdfspath/spark_graphx.db/give_credit \
	--columns  "id,name,age" \     #为数据库中的字段名称
	--input-null-string  '\\\\N'  \
	--input-null-non-string  '\\\N' \
	--input-fields-terminated-by  "#" \
	-m 30
	(注意:hive导入到pg或mysql数据库中,需要在pg或mysql数据库中先建好表)

加:使用sqoop导mysql数据到hive中报错问题参考:
http://www.cnblogs.com/harrymore/p/9057096.html#_labelTop

你可能感兴趣的:(Sqoop)