Sqoop1.4.6安装使用及避坑

通过这么几天的折腾,发现 Sqoop1 真的比 Sqoop2 方便好用的多,Sqoop2 坑真是太多了,搞不定。Sqoop1 坑少也稳定,可是零基础使用过程当中也是有几点须要注意的。html

官方下载:Sqoop 官网 
官方使用文档 
Sqoop-1.4.6安装部署及详细使用介绍 
若是像我同样直接用CDH里边自带的话,方便的地方是环境变量什么的不须要我再去配置了,很方便。 
要检查安装成功没,直接 sqoop version;mysql

命令行使用

1 : 
可能会出现警告: 
accumulo does not exist! Accumulo imports will fail. 
hcatalog does not exist! hcatalog imports will fail. 
方法一: 
CDH官方方法,以下: 
Services that you want to use with Sqoop, such as HBase, Hive HCatalog, and Accumulo. When you run Sqoop, it checks to see if these services are installed and configured. It logs warnings for services it does not find. These warnings, shown below, are harmless. You can suppress these error messages by setting the variables $HBASE_HOME, $HCAT_HOME and $ACCUMULO_HOME to any existing directory.sql

即:只须要把 $HBASE_HOME, $HCAT_HOME and $ACCUMULO_HOME 设置为任意一个存在的目录便可。好比我:export ACCUMULO_HOME=/root, 果真就不报警告了,很是简单方便,强烈推荐。并且使用方法二的话直接修改了配置文件颇有可能会出问题,不安全数据库

方法二: 
若是不须要,能够屏蔽它; 
到 “SQOOP_HOME/bin” 下编辑 configure-sqoop,注释掉里边与Accumulo 和 hcatalog 有关的代码块,不是太难,本身打开看看这个文件就知道了。apache

2:要注意 “–target-dir” 须要指定一个空的不存在的文件夹,不能指定已经存在的文件夹,它会本身建立的安全

3:一个 从 Oracle 到 HDFS 的 import 语句:oracle

sqoop import --connect jdbc:oracle:thin:@<HOST>:1521:app --username user --P --query "select * from HD.STORE where \$CONDITIONS and RCVTIME < TO_TIMESTAMP('2017-05-30 00:00:00','yyyy-mm-dd hh24:mi:ss.ff')" --split-by id --direct  --target-dir /user/root/store --m 1
  • 1

这里边几点须要注意的坑:app

  • “–connect “:CDH Sqoop1 使用 里边用一些 JDBC Connection Strings 的语法介绍和例子,可是 Oracle 的我试了不行,正确的写法应该如:jdbc:oracle:thin:@<HOST>:<PORT>:<DATABASE_NAME>,区别在于 thin 后边是须要又一个 冒号 的,很容易错,还有 与 中间的链接也是冒号,由于有的写法是 “/“,可是这里须要注意的是,这里是 冒号。less

  • “–query“:ide

    • 若是这里SQL语句里边用过单引号了,那外边必需要用双引号
    • 这里的SQL假如直接使用 “FROM STORE“的话,是会报 table 找不见,或者不存在的,由于使用“–query“的话没有指定 Schema ,因此这里必须使用 .

      的形式

       

    • where 后边必须有 $CONDITIONS 条件,sqoop 运行的时候,看日志发现sqoop 会在这里插入(1=0)或(1=1)来控制这条语句的执行。外边使用双引号的话,$CONDITIONS 前边须要加反斜杠 即:\$CONDITIONS。 
      Free form query in Sqoop Import with WHERE clause

  • “–split-by” :须要指定一个 int 类型的列名,通常是主键。sqoop 会计算这个字段的 MIN 和 MAX ,而后结合 fetchSize 来肯定 怎么切分数据块。这个字段必填。

  • “–direct“:没加这个以前,导入特别慢,中间常常会出现 “Connect reset“,这个不要紧,一下子它又回自动链接上。可是确实太慢了。使用这个字段后,导入速度又快又稳定,这个字段表明的意思应该是 使用的是关系数据库自带的导入导出工具。最好加上这个字段配置。

–options-file 使用

为了方便复用,咱们能够把一串命令和参数写入txt文件中,使用 –options-file 来调用。详细使用方法,官方文档的 6.4 Using Options Files to Pass Arguments 里写的特别清楚了。由于是英文的,我这里简单给英文很差的同窗说一下要点和更命令行方式对比须要注意的: 
先上一个等同上面命令行例子的例子。

store_import.txt

#
# import options file of STORE table
#

#
# oracle table STORE to hive table *
#

import
--connect
jdbc:oracle:thin:@<HOST>:1521:app
--username
user
--password
123456
--query
select * from HD.STORE where $CONDITIONS and \
RCVTIME < TO_TIMESTAMP('2017-05-30 00:00:00','yyyy-mm-dd hh24:mi:ss.ff')
--split-by
FLOWNO
--direct
--target-dir
/user/root/store
--m
1

用时,

$ sqoop --options-file /users/home/store_import.txt
  • 1
  1. 文件要是 txt 文件形式
  2. 里边的参数和值的顺序跟命令行里的一行,可是都必须如上同样换行,一行一个
  3. 这里密码咱们用了 --password直接写入密码,方便自动执行;命令行里咱们用的是-P,用-P为了安全,在命令行执行时须要手动输入密码,并且不会明文显示
  4. 变化较大的是 --query 参数后边的SQL语句,须要注意:

    • 参数和值通常一行一个,可是若是就像SQL语句同样,长的话能够在结尾使用反斜杠来换行
    • 通常不要用双引号,除非双引号里边包含单引号,使用双引号的话就不能再使用换行符了,双引号必须在同一行。
    • 这里的 $CONDITIONS 前边再也不须要反斜杠来转换$符号了

上面的例子都是从 oracle 导入 hdfs 的,如今咱们用 sqoop 来直接导入 Hive。

导入数据到Hive

官方文档 7.2.12. Importing Data Into Hive 
而后再上个人例子,

import
--hive-import
--hive-table
dw_hd.ods_store
--connect
jdbc:oracle:thin:@<HOST>:1521:app
--username
user
--password
123456
--query
select * from HD.STORE where $CONDITIONS and \
RCVTIME < TO_TIMESTAMP('2017-05-30 00:00:00','yyyy-mm-dd hh24:mi:ss.ff')
--split-by
FLOWNO
--direct
--target-dir
/user/root/store
--null-string
'\\N'
--null-non-string
'\\N'
--m
2

sqoop 导入 Hive 分三步: 
1. 先导入--target-dir 指定的 HDFS 的目录中 
2. 在 Hive 中建表 
3. 调用 Hive 的 LOAD DATA INPATH 把 --target-dir中的数据移动到 Hive 中

观察上边例子与前边的作对比,有如下几点不一样:

  • --hive-import :指定是导入 Hive
  • --hive-table:导入 Hive 中的数据库名和表名
  • --null-string和 --null-non-string:分别表明了 sqoop 对 字符串类型 null 值 和 非字符串类型 null 值 的处理。若是不指定的话,默认导入 Hive 后 字符串类型的 null 值是 ‘null’,非字符串类型 null 值是 ‘NULL’,这里用把这两种状况统一成了 ‘NULL’,sqoop 中用 ‘\N’,若是想要小写的 ‘null’ 的话,使用 ‘\N’。

问题1:导入后从Hive中查到的数据条数比实际从关系数据库中查到的条数多? 
解决:缘由是使用--hive-import 会使用默认的 Hive 的分隔符,值分隔符^A和行分隔符\n官方文档 7.2.12. Importing Data Into Hive 里原文以下: 
Hive will have problems using Sqoop-imported data if your database’s rows contain string fields that have Hive’s default row delimiters (\n and \r characters) or column delimiters (\01 characters) present in them. You can use the --hive-drop-import-delims option to drop those characters on import to give Hive-compatible text data. Alternatively, you can use the --hive-delims-replacement option to replace those characters with a user-defined string on import to give Hive-compatible text data. These options should only be used if you use Hive’s default delimiters and should not be used if different delimiters are specified.

Sqoop will pass the field and record delimiters through to Hive. If you do not set any delimiters and do use --hive-import, the field delimiter will be set to ^A and the record delimiter will be set to \n to be consistent with Hive’s defaults.

这样问题就来了,若是导入的数据中有’\n’,hive会认为一行已经结束,后面的数据被分割成下一行。这种状况下,导入以后hive中数据的行数就比原先数据库中的多,并且会出现数据不一致的状况。 
Sqoop也指定了参数 --fields-terminated-by和 --lines-terminated-by来自定义行分隔符和列分隔符。 
但是当你真的这么作时 坑爹呀! 
INFO hive.HiveImport: FAILED: SemanticException 1:381 LINES TERMINATED BY only supports newline ’\n’ right now. 也就是说虽然你经过--lines-terminated-by指定了其余的字符做为行分隔符,可是hive只支持\n做为行分隔符。

ORACLE中查询某个字段包含 回车 换行 符,||不是或,是 oracle 中的字符串链接符。%是通配符,表明任意字符串。 
查看是否包含 回车换行 符,即:\r\n 
select * from system.test_tab1 where name like '%'||chr(13)||chr(10)||'%' 
单独查看是否包含 回车换行 符,即:\r 
select * from system.test_tab1 where name like '%'||chr(13)||'%' 
单独查看是否包含 换行 符,即:\n 
select * from system.test_tab1 where name like '%'||chr(10)||'%'

解决方法:简单的解决办法就是加上参数--hive-drop-import-delims来把导入数据中包含的hive默认的分隔符去掉。这个最简单,若是肯定数据中不应含有这些字符的话,或者肯定去掉没影响的话,能够用这个。另外,使用这个就无法使用 --direct 选项了。

增量导入

7.2.9. Incremental Imports 
问题:–incremental lastmodified 模式 不支持 导入Hive 
--incremental lastmodified option for hive imports is not supported. Please remove the parameter --incremental lastmodified. 
解决办法:使用导入HDFS 的方法,只不过 --target-dir 设置成 Hive table 在 HDFS 中的位置,相似于/user/hive/warehouse/store,前提 Hive 中已经存在这个表了,不存在的话先CREATE。 
sqoop incremental import to hive table 

问题1:导入后每一行全部数据都在第一个字段里? 
缘由和解决:由于直接导入 HDFS 中 HIve 里的文件夹下的话,sqoop 默认给的 值分隔符 是逗号 ,而 Hive 默认值分割符是\001,即:^A,因此 Hive 是不认的,因此 须要 把值分隔符改为 ^A,即加上下边的配置:

--fields-terminated-by
\001

问题2:仍是上边那个问题,导入后从Hive中查到的数据条数比实际从关系数据库中查到的条数多? 
缘由和解决:这样子增量导入时,由于直接是导入 hdfs 的,不是 --hive-import,因此就无法 用 --hive-drop-import-delims 去掉冲突的分隔符了。因此就又会出现上边那个问题。解决办法是:在 --query 后的SQL语句里作 replace 方法嵌套作替换,把\r\n分别替换为空字符串, REPLACE(REPLACE(name,CHR(13),''),CHR(10),''),以下:

--query
select REPLACE(REPLACE(name,CHR(13),''),CHR(10),'') name,code from test

定义 sqoop job 增量导入

文档 12. Saved Jobs 
用 sqoop job 作增量更新,它会在它的 metastore 中管理 --last-value,很方便。

sqoop job --create test_import_store -- --options-file /root/sqoop_option_files/store_import.txt
  • 1

这里有一个很弱智的坑,很容易栽进来,困了我快一天。

通常网上定义job的例子以下:

sqoop job --create user_info -- import --connect jdbc:mysql://mysql-server-ip:3306/sqoop --username root --password root --table user_info -m 1
  • 1

看这里,sqoop job --create user_info -- import,看到了吗,’–’ 和 ‘import’ 之间有一个空格,很容易忽视的一点。这里用 ‘–’ 来指示 job 的内容,第一次见,很容易把 –import 当成一个总体。不注意这个,就会一直报 不能识别的参数 
ERROR tool.BaseSqoopTool: Unrecognized argument

这里我以为,sqoop job 和 –options-file 一块用才更配,很方便去编辑 job,以下同样的模版,很容易避开上边那个坑。

sqoop job --create <job_name> -- --options-file <options-file-txt-path>
  • 1

在metastore中保存密码

默认每次执行 job 时都须要手动输入密码。这样很不利于自动化任务和 Oozie 调度,因此须要设置在 sqoop metastore 中保存密码。 
You can enable passwords in the metastore by setting sqoop.metastore.client.record.password to true in the configuration.

解决方式有两种: 
第一种方式,使用password-file; 
第二种方式,在sqoop-site.xml中添加以下属性便可(添加后第一次仍然须要输入密码 )。

<property>
   <name>sqoop.metastore.client.record.password</name>
   <value>true</value>
</property>
  • sqoop 经常使用命令

Sqoop详细介绍包括:sqoop命令,原理,流程 
Sqoop使用手册

安装Hue后的一些功能的问题解决干货总结(博主推荐)

相关文章
相关标签/搜索