import工具从RDBMS向HDFS导入单独的表。表格中的每一行都表示为HDFS中的单独记录。记录可以存储为文本文件(每行一个记录),或以Avro或SequenceFiles的二进制表示形式存储。
$ sqoop-import (generic-args) (import-args)
Hadoop的通用参数必须在前,而后是导入参数,导入参数的顺序随意。
以下是连接数据库的相应参数:
--connect <jdbc-uri>:指定JDBC连接字符串。
--connection-manager <class-name>:指定要使用的连接管理器类。
--driver <class-name>:手动指定要使用的JDBC驱动程序类。
--hadoop-mapred-home <dir>:覆盖$ HADOOP_MAPRED_HOME--help打印使用说明。
--password-file:为包含认证密码的文件设置路径。
-P:从控制台读取密码。
--password <password>:设置验证密码。
--username <username>:设置验证用户名。
--verbose:在控制台打印更多信息。
--connection-param-file <filename>:提供连接参数的可选属性文件。
--relaxed-isolation:将连接事务隔离设置为对映射器未提交的读取。
以下是安全验证参数:
--validate:启用对复制数据的验证,仅支持单个表复制。
--validator <class-name>:指定要使用的验证程序类。
--validation-threshold <class-name>:指定要使用的验证阈值类。
--validation-failurehandler <class-name>:指定要使用的验证失败处理程序类。
以下是Sqoop在导入数据时,可选的控制导入数据内容的参数:
--append:将数据追加到HDFS中的现有数据集。
--as-avrodatafile:将数据导入Avro数据文件。
--as-sequencefile:将数据导入到SequenceFiles。
--as-textfile:以纯文本形式导入数据(Sqoop导入的默认方式)。
--as-parquetfile:将数据导入Parquet文件。
--boundary-query <statement>:边界查询用于创建分割。
--columns <col,col,col…>:从表中选择要导入列。
--delete-target-dir:删除导入目标目录(如果存在)。
--direct:如果数据库存在,则使用直接连接器。
--fetch-size <n>:一次从数据库读取的条目数。
--inline-lob-limit <n>:设置内联LOB的最大大小。
-m,--num-mappers <n>:使用n个map任务执行导入。
-e,--query <statement>:导入结果statement。
--split-by <column-name>:用于分割表单元的表格列。不能与--autoreset-to-one-mapper选项一起使用 。
--split-limit <n>:每个拆分大小的上限。这仅适用于整数和日期列。对于日期或时间戳字段,它以秒计算。
--autoreset-to-one-mapper:如果表中没有主键并且没有提供分割列,导入应该使用一个mapper。不能与--split-by <col>选项一起使用。
--table <table-name>:导入的表名。
--target-dir <dir>:目标HDFS目录。
--temporary-rootdir <dir>:导入期间创建的临时文件的HDFS目录(覆盖默认的“_sqoop”)。
--warehouse-dir <dir>:表目的地的HDFS父级目录。
--where <where clause>:在导入过程中使用WHERE子句。
-z,--compress:启用压缩。
--compression-codec <c>:使用Hadoop编解码器(默认gzip)。
--null-string <null-string>:要为字符串列写入空值的字符串。
--null-non-string <null-string>:要为非字符串列写入空值的字符串。
--null-string和--null-non-string参数都是可选的。如果未指定,那么字符串“null”将被使用。
以下是导入到Hive中时可选的参数:
--hive-home <dir>:覆盖 $HIVE_HOME。
--hive-import:将表导入Hive(如果没有设置,则使用Hive的默认分隔符。)
--hive-overwrite:覆盖Hive表中的现有数据。
--create-hive-table:如果设置,那么如果存在目标hivetable,作业将失败。默认情况下,此属性为false。
--hive-table <table-name>:设置导入到Hive时要使用的表名。
--hive-drop-import-delims:导入到Hive时,从字符串字段中删除\n、\r和\01。
--hive-delims-replacement:在导入到Hive时,将字符串字段中的\n、\r和\01替换为用户定义的字符串。
--hive-partition-key:分配到分区的Hive字段的名称。
--hive-partition-value <v>:作为该任务导入到Hive中的分区键的字符串值。
--map-column-hive <map>:覆盖从SQL类型到配置列的Hive类型的默认映射。如果在此参数中指定逗号,请使用URL编码的键和值,例如,使用DECIMAL(1%2C%201)而不是DECIMAL(1,1)。
以下是要导入HBase时可选的参数:
--column-family <family>:设置导入的目标列族。
--hbase-create-table:如果指定,则创建缺少的HBase表。
--hbase-row-key <col>:指定哪个输入列用作行键如果输入表包含复合键,那么<col>必须以a的形式出现,逗号分隔组合键、列表、属性。
--hbase-table <table-name>:指定要用作目标而不是HDFS的HBase表。
--hbase-bulkload:启用批量加载。
以下是要将数据导入Accumulo时可选的参数:
--accumulo-table <table-nam>:指定一个Accumulo表作为导入目标表。
--accumulo-column-family <family>:设置导入的目标列族
--accumulo-create-table:如果指定,则创建没有的Accumulo表。
--accumulo-row-key <col>:指定哪个输入列用作行键
--accumulo-visibility <vis>:(可选)指定一个可见性标记以应用于插入到Accumulo中的所有行。默认是空字符串。
--accumulo-batch-size <size>:(可选)设置Accumulo写入缓冲区的大小(以字节为单位)。默认值是4MB。
--accumulo-max-latency <ms>:(可选)为Accumulo批处理写入器设置最大等待时间(以毫秒为单位)。缺省值是0。
--accumulo-zookeepers <host:port>:由Accumulo实例使用的Zookeeper服务器的逗号分隔列表。
--accumulo-instance <table-name>:目标Accumulo实例的名称。
--accumulo-user <username> :要导入为的Accumulo用户的名称。
--accumulo-password <password> :Accumulo用户的密码
Sqoop提供了两种文件格式用于存储导入的数据,分别是:分隔文本和SequenceFiles。
分隔文本是默认的导入数据存储格式。也可以使用--as-textfile参数显式指定。该方式将每个基于字符串的表示形式的记录写入分割文件中,在各个行和列之间使用分隔符进行行列的划分。分隔符可以是逗号、制表符或其他字符。以下是基于分割文本导入数据的示例:
1,这里是一条消息,2010-05-01
2,新年快乐!,2010-01-01
3,另一个消息,2009-11-12
分隔文本适用于大多数非二进制数据类型。它也支持其他工具的进一步操作,例如Hive。
SequenceFiles是一种二进制格式,它将单个记录存储在自定义的特定的数据类型记录中。这些数据类型表现为Java类。Sqoop会自动生成这些数据类型。这种格式支持二进制表示中所有数据的准确存储,适用于存储二进制数据(例如,VARBINARY列)或将主要由自定义MapReduce程序操作的数据。从SequenceFiles读取性能高于从文本文件读取数据,因为记录不需要被解析。
Avro数据文件是一种紧凑且高效的二进制格式,可与使用其他编程语言编写的应用程序进行交互操作。Avro还支持版本控制,以便在添加或删除列时,将以前导入的数据文件和新文件一起处理。
默认情况下,导入的数据未被压缩。可以使用-z或--compress参数的deflate(gzip)算法来压缩数据,或使用--compression-codec参数指定Hadoop压缩编解码器。压缩可以用于SequenceFile,文本和Avro文件。
Sqoop以特定的方式处理大型对象(BLOB和CLOB列)。如果这个数据确实很大,那么这些列不应该像大多数列那样完全具体化在内存中进行操作。相反,他们的数据是以流的方式处理的。大型对象可以内联存储其余的数据,在这种情况下,在每次访问时它们都完全物化在内存中,或者它们可以存储在连接到主数据存储的辅助存储文件中。
默认情况下,小于16MB的大对象将内联存储到其他数据中。如果大小较大,则将它们存储在导入目标目录的_lobs子目录中的文件中。这些文件以针对大型记录存储优化的单独格式存储,可以容纳每个记录最多2^63字节的记录。
lob溢出到单独文件的大小由--inline-lob-limit参数控制,该参数指定要保持内联的最大lob大小(以字节为单位)。如果将内联LOB限制设置为0,则所有大型对象都将放置在外部存储中。
--enclosed-by <char>:设置必需的字段包围字符。
--escaped-by <char>:设置转义字符。
--fields-terminated-by <char>:设置字段分隔符。
--lines-terminated-by <char>:设置行尾字符。
--mysql-delimiters:使用MySQL的默认分隔符集:字段:逗号(,)行:换行(\n)转义:反斜杠(\)包含:单引号(’)。
--optionally-enclosed-by <char>:设置字段包围字符。
导入数据到分隔文本时,分隔符的选择很重要。如果字符串包含的字符中出现了分隔符,那么会导致后续分析过程无法清晰地解析导入的数据。
例如,字符串"Hello, pleased to meet you"不应将字段结尾分隔符设置为逗号。
分隔符可以被指定为:
1.一个字符(--fields-terminated-by X)
2.一个转义字符(--fields-terminated-by \t)。支持的转义字符是:
\b(退格)、\n(新行)、\r(回车)、\t(制表符)、\"(双引号)、\\'(单引号)、\\(反斜杠)、\0(NUL)。
\0(NUL):表示在字段或行之间插入NUL字符,如果使用--enclosed-by、--optionally-enclosed-by或--escaped-by参数可以控制禁用/启用。
3.UTF-8字符代码点的八进制表示。形式为:\0ooo,其中OOO是八进制的值。
例如:--fields-terminated-by \001会产生^A字符。
4.UTF-8字符代码点的十六进制表示。形式为:\0xhhh,其中hhh是十六进制的值。
例如:--fields-terminated-by \0x10会产生回车符。
默认用于字段的分隔符是逗号(,),行数据的分隔符是换行符(\n),不用引号或者转义字符。
注意:如果在导入数据的字段中包含逗号或换行符,会导致数据分割模糊、不可分。为了明确解析,两者都必须启用。例如,通过--mysql-delimiters。
如果无法提供明确的分隔符,请使用包含字符和转义字符。包含字符和转义字符的组合可以明确地解析行。
例如:假设数据集的一列包含以下值:
Some string, with a comma.
Another "string with quotes"
以下参数将提供可以明确解析数据的分隔符:
$ sqoop import --fields-terminated-by , --escaped-by \\ --enclosed-by '\"' ...
注意,为了防止shell破坏包含字符,使用单引号将参数值引起来。
以上命令应用于上述数据集的结果是:
"Some string, with a comma.","1","2","3"...
"Another \"string with quotes\"","4","5","6"...
这里导入的字符串显示在附加列("1","2","3"等)的上下文中,以演示包含和转义的全部效果。只有在分隔符字符出现在导入的文本中时,包含字符才是必需的。因此可以将包含字符指定为可选:
$ sqoop import --optionally-enclosed-by '\"' (the rest as above)...
导入数据的结果将是以下形式:
"Some string, with a comma.",1,2,3...
"Another \"string with quotes\"",4,5,6...
注意:
尽管Hive支持转义字符,但它不能处理换行字符的转义。此外,它不支持将可能包含内联字符串中的字段分隔符的字符括起来的概念。因此,建议您在使用Hive时,选择明确的字段和记录终止分隔符,而不需要转义和包含字符;这是由于Hive的输入解析能力有限。如果将数据导入Hive时不使用--escaped-by,--enclosed-by或--optionally-enclosed-by参数指定分隔符,则Sqoop将报警。
--mysql-delimiters参数是一个简短的参数,它使用mysqldump的默认分隔符。如果将mysqldump分隔符与direct模式(使用--direct)一起使用,则可以实现非常快速的导入。
分隔符的选择对于分割文本模式导入重要,使用--as-sequencefile导入到SequenceFiles仍然相关。生成类的toString()方法将使用前面指定的分隔符,因此输出数据的后续格式将依赖于选择的分隔符。
--input-enclosed-by <char>:设置必需的字段封闭器
--input-escaped-by <char>:设置输入转义字符
--input-fields-terminated-by <char>:设置输入字段分隔符
--input-lines-terminated-by <char>:设置输入的行尾字符
--input-optionally-enclosed-by <char>:设置字段包围字符
当Sqoop将数据导入到HDFS时,它会生成一个Java类,它可以重新解释它在进行分隔格式导入时创建的文本文件。分隔符的选择有如下参数:
--fields-terminated-by:此项将控制数据如何写入磁盘,以及生成的parse()方法如何重新解释这些数据。parse()方法使用的分隔符可以独立于输出参数,通过--input-fields-terminated-by来选择。
Sqoop旨在将数据库中的表导入HDFS。
要连接数据库需要使用--connect参数。此参数的值为要连接的数据库的地址,形式和数据库驱动地址一样。
例如:以下是连接MySQL数据库的命令。
$ sqoop import --connect jdbc:mysql://database.example.com/employees
Sqoop支持多种数据库。Sqoop会自动处理以jdbc:mysql://开头的连接字符串。Sqoop也可以使用其他JDBC兼容的数据库。
步骤如下:
首先,为要导入的数据库类型下载相应的JDBC驱动的jar包。
然后,将jar包拷贝到$SQOOP_HOME/lib目录中。如果是用RPM或Debian的方式安装的话,目录为:/usr/lib/sqoop/lib。
最后,将数据库驱动类提供给Sqoop的--driver参数,作为此参数的值。
例如:经常使用的MySQL驱动:com.mysql.jdbc.Driver
$ sqoop import --driver com.mysql.jdbc.Driver \
--connect <connect-string> ...
例如:要连接到SQLServer数据库,首先要下载驱动jar包并将其拷贝到Sqoop lib路径中。然后运行Sqoop。命令如下:
$ sqoop import --driver com.microsoft.jdbc.sqlserver.SQLServerDriver \
--connect <connect-string> ...
使用JDBC连接到数据库时,可以使用--connection-param-file选项通过属性文件选择性地指定额外的JDBC参数。这个文件的内容被解析为标准Java属性,并在创建连接时传递给驱动程序。
注意:通过可选属性文件指定的参数仅适用于JDBC连接。任何使用非JDBC连接的快速路径连接器都将忽略这些参数。
--username参数用来提供数据库的用户名。
Sqoop提供了几种不同的提交密码的方法,下面详细描述数据库提供安全和不安全的密码提交方式。
将密码保存在具有400权限的用户主目录中的文件中,并使用--password-file参数指定该文件的路径,这是输入密码的首选方法。
Sqoop会从文件中读取密码,并使用安全的方式将它传递给MapReduce集群,而不必在配置中公开密码。包含密码的文件可以位于本地磁盘或HDFS上。
例如:
$ sqoop import --connect jdbc:mysql://database.example.com/employees \
--username venkatesh --password-file ${user.home}/.password
注意:Sqoop将读取密码文件的全部内容用作密码。包括空格字符。需要确保密码文件仅包含属于密码的字符。
在命令行中,可以使用echo -n来存储密码,这样将不会产生多余字符。
例如:存储secret为密码,可以使用如下命令:
echo -n "secret" > password.file
提供密码的另一种方式是使用-P参数,它将从控制台提示符处读取密码。
Hadoop 2.6.0提供了一个API来将密码存储与应用程序分开。有一个新的credential命令行工具来管理密码及其别名。密码与其别名一起存储在密码保护的密钥库中。密钥库密码可以通过环境变量提供给命令行的密码提示,也可以默认为软件定义的常量。Hadoop文档中有关于此功能的使用说明。
一旦使用Credential Provider工具存储密码并且Hadoop配置已经适当更新后,所有应用程序都可以选择使用别名代替实际密码,并在运行时解析别名以供使用密码。
由于用于存储凭证提供程序的密钥库或类似技术是通过组件共享的,因此各种应用程序,各种数据库和其他密码可以安全地存储在其中,并且只有别名才需要在配置文件中公开,从而保护密码免受可见。
如果Sqoop依赖的Hadoop支持这种功能的话,那么Sqoop也允许使用这种功能。此功能引入了一个新选项--password-alias来在命令行上提供别名,而不是实际的密码。此选项的参数值是与实际密码关联的存储器上的别名。用法示例如下所示:
$ sqoop import --connect jdbc:mysql://database.example.com/employees \
--username dbuser --password-alias mydb.password.alias
如果命令行的首选项不是此选项,则可以将别名保存在--password-file选项提供的文件中。除此之外,Sqoop配置参数org.apache.sqoop.credentials.loader.class应该设置为提供别名解析的类名:org.apache.sqoop.util.password.CredentialProviderPasswordLoader
示例用法如下(假设.password.alias具有真实密码的别名):
$ sqoop import --connect jdbc:mysql://database.example.com/employees \
--username dbuser --password-file ${user.home}/.password-alias
注意:
--password参数是不安全的,因为其他用户可能通过程序的输出从命令行参数中读取密码,密码仍然使用不安全的方式在MapReduce集群的节点之间传输。例如:
$ sqoop import --connect jdbc:mysql://database.example.com/employees \
--username aaron --password 12345
Sqoop通常以表格为单位的方式导入数据。导入的数据各个节点都是可选的,例如要导入的表、表中的字段、表中的数据等等。
--table参数用来选择要导入的表。
例如:--table employees。
该参数还可以标识数据库中的一张表或其他类似表的实体。
默认情况下,表格中的所有列都被选中用于导入。导入的数据以“自然顺序”写入HDFS。
例如:包含列A,B和C的表数据导入结果如下:
A1,B1,C1
A2,B2,C2
...
导入的列是可选的,使用--columns参数控制列的数量以及排序。使用“,”号进行列分割。
例如:
--columns "name,employee_id,jobtitle"
导入的数据也是可选的,使用--where参数可以附加一个WHERE子句来选择要导入的数据。默认情况下,Sqoop生成表单的语句如下:
SELECT <column list> FROM <table name>
例如:--where "id > 400"。只有列id值大于400的行才会被导入。
默认情况下,sqoop使用select min(<split-by>),max(<split-by>) from <table name>查询找出创建分割的边界。在某些情况下,这个查询不是最优化的,所以可以使用--boundary-query参数指定列作为边界。
Sqoop也可以导入任意SQL查询的结果集。除了使用的--table,--columns和--where参数,还可以指定--query的参数,其参数值为简单SQL语句。
导入查询结果集时,必须使用--target-dir参数指定目标目录。
如果要启动多个mapper并行执行导入的话,则每个mapper都需要执行查询的语句,这样就需要Sqoop推断出每个进程需要执行的任务边界,那么就需要使用--split-by指定一个列来进行任务边界判断的依据,这个列最好是整数类型而且没有跳跃值的列,这样可以使每个进程能够得到均分的任务。
例如:
$ sqoop import \
--query 'SELECT a.*, b.* FROM a JOIN b on (a.id == b.id) WHERE $CONDITIONS' \
--split-by a.id --target-dir /user/foo/joinresults
或者,查询可以被执行一次并连续导入,方法是指定一个映射任务-m 1:
$ sqoop import \
--query 'SELECT a.*, b.* FROM a JOIN b on (a.id == b.id) WHERE $CONDITIONS' \
-m 1 --target-dir /user/foo/joinresults
注意:
1.如果使用双引号(“)将查询语句引起来的话,则必须使用\$CONDITIONS进行转义,而不是$CONDITIONS, 转义之后shell才会将其视为shell变量。双引号查询语句如下所示:
"SELECT * FROM x WHERE a='foo' AND \$CONDITIONS"
2.在当前版本的Sqoop中使用SQL查询的功能仅限于简单查询,其中不能包含模糊查询和where子句中的OR条件。使用复杂的查询,可能会导致意想不到的结果。
从数据库导入数据的时候可以使用-m或--num-mappers参数来增加导入任务的并行。这些参数中的每一个参数值都是整数,该值与使用的并行度相对应。默认情况下,使用四个任务。有些数据库可能会通过将此值增加到8或16来提高性能。
注意:
1.不要将并行度提高到大于MapReduce集群中可用的最大数量,如果超过,任务将连续运行,并可能增加执行导入所需的时间。
2.不要将并行度设置的高于数据库可以合理支持的程度。例如:将100个并发客户端连接到数据库可能会增加数据库服务器的负载,从而导致性能受到影响。
在执行并行导入时,Sqoop需要一个可以分割工作负载的标准。Sqoop使用列来分割工作量。默认情况下,Sqoop将识别表中的主键列(如果存在)并将其用作拆分列。分割列的低值和高值从数据库中检索,并且mapper任务在总范围的大小均匀的分量上进行操作。
例如:有一个表的主键列id最小值为0,最大值为1000,并且Sqoop指向使用4个任务,则Sqoop将运行四个进程,每个进程都执行如下的SQL语句:
SELECT * FROM sometable WHERE id >= lo AND id < hi
每个mapper任务的(lo, hi)的值分别对应为(0,250),(250,500),(500,750)和(750,1001)。
如果主键的实际值在其范围内不均匀分布,则可能导致任务不平衡。应该明确地选择与--split-by参数不同的列。
例如,--split-by employee_id。
Sqoop目前不能在多列索引上拆分。如果表格没有索引列,或者有多列键,那么必须手动选择拆分列。
可以使用--split-limit参数替换--num-mapers参数。使用--split-limit参数会限制所创建的拆分部分的大小。如果创建的分割大小大于此参数中指定的大小,则分割将根据此限制调整大小,并且分割的数量也根据此 项变化。如果根据--num-mappers参数计算出的分割大小超过了--split-limit参数设置的大小,那么将增加实际的mapper数量。如果--split-limit 参数中指定的值为0或负数,则该参数将被全部忽略,分割大小将根据mapper的数量计算。
如果一个表没有定义主键并且--split-by <col>参数也没有指定,那么导入将会失败,除非使用--num-mappers 1选项或使用--autoreset-to-one-mapper选项将mapper的数量显式设置为1。--autoreset-to-one-mapper选项通常与import-all-tables工具一起使用,自动处理没有主键的表。
每次启动Sqoop作业时,Sqoop都会将$ SQOOP_HOME / lib文件夹中的jar包复制到作业缓存中。当由Oozie启动时则不用,因为Oozie使用它自己的Sqoop共享库,它将Sqoop依赖关系保留在分布式缓存中。Oozie将在第一个Sqoop作业期间对Sqoop依赖关系的每个工作节点执行本地化,并将工作节点上的jar包重用于子作业。
在Oozie启动时使用Sqoop命令中的--skip-dist-cache选项,将跳过Sqoop复制依赖关系到作业缓存并保存大量I/O的步骤。
默认情况下,导入过程将使用供应商提供的JDBC导入通道。一些数据库可以使用特定的数据移动工具以更高性能的方式执行导入。
MySQL提供的mysqldump工具可以非常快速地将数据从MySQL导出到其他系统。Sqoop可以通过--direct参数指定该工具导入,比使用JDBC性能更高。
默认情况下,Sqoop将数据导入HDFS中一个名为foo的目录中。
例如,用户名是someuser,则导入工具会将数据写入/user/someuser/foo/(files)中。
可以使用--warehouse-dir参数调整导入的这个目录。
例如:
$ sqoop import --connnect <connect-str> --table foo --warehouse-dir /shared
该命令将数据写入目录/shared/foo/目录下的文件中。
可以明确地选择目标目录,如下所示:
$ sqoop import --connnect <connect-str> --table foo --target-dir /dest
上述命令将文件导入到/dest目录中。--target-dir与--warehouse-dir不相容。只能使用两者之一。
使用direct模式时,可以指定应传递给底层工具的其他参数。如果参数--是在命令行上 出现的,则--后的参数将直接发送到底层工具。
例如,以下内容将调整mysqldump使用的字符集:
$ sqoop import --connect jdbc:mysql://server.foo.com/db --table bar \
--direct -- --default-character-set=latin1
默认情况下,数据将导入到新的目标位置。如果目标目录已经存在于HDFS中,Sqoop将拒绝导入并覆盖该目录的内容。
如果使用--append参数,Sqoop会将数据导入临时目录,然后以不与该目录中现有文件名冲突的方式将文件重命名为正常目标目录。
默认情况下,Sqoop在mapper中导入数据使用读提交事务隔离。这可能不是所有ETL工作流程中的理想选择,并且可能希望减少隔离保证。Sqoop使用--relaxed-isolation选项可以指定读取的事物隔离级别。
--read-uncommitted隔离级别不支持所有数据库(例如Oracle),因此指定选项--relaxed-isolation可能无法在所有数据库的支持。
Sqoop预先配置为将大多数SQL类型映射到适当的Java或Hive类型。默认映射可能并不适合每个场景,可以使用--map-column-java(用于更改映射到Java)或--map-column-hive(用于更改Hive映射)进行更改。
--map-column-java <mapping>:指定已配置列从SQL到Java类型的映射。
--map-column-hive <mapping>:指定从SQL到配置列Hive类型的映射。
Sqoop以<列名称> = <新类型>形式的逗号分隔映射列表。
例如:
$ sqoop import ... --map-column-java id = String,value = Integer
注意:在--map-column-hive选项中需要逗号分割,应使用URL编码的键和值,例如,使用DECIMAL(1%2C%201)而不是DECIMAL(1,1)。如果某些配置的映射不可用,Sqoop会抛出异常。
当sqoop从企业存储导入数据时,表名和列名可能不是有效的Java标识符或Avro/Parquet标识符。为了解决这个问题,sqoop将这些字符翻译为_作为创建的一部分。任何以_(下划线)字符开头的列名将被翻译为具有两个下划线字符。
例如:_AVRO将被转换为__AVRO。
在HCatalog导入的情况下,当映射到HCatalog列时,列名将转换为小写。
Sqoop提供了一种增量导入模式,可用于检索比以前导入的一组行更新的行数据。
以下参数控制增量导入:
--check-column (col):要导入某些行时要检查的列。(该列不能是CHAR/NCHAR/VARCHAR/VARNCHAR/LONGVARCHAR/LONGNVARCHAR类型)。
--incremental (mode):指定Sqoop如何确定哪些行是新的。此项参数的值有append和lastmodified两个。
--last-value (value):指定先前导入中的检查列的最大值。
Sqoop支持两种方式的增量导入:append和lastmodified。可以使用该--incremental参数来指定要执行的增量导入的方式。
append方式在导入表格时,必须指定起始行id列所对应的值。可以通过--check-column指定该行包含的列。Sqoop导入行的检查列的值是否大于--last-value参数指定的值。
Sqoop支持的备用表更新策略称为lastmodified模式。
当源表的行更新时,每次更新都会将最后更新的列的值设置为当前的时间戳,如果行检查的列的时间戳比--last-value指定的时间戳新,那么该行会被导入。
在增量导入结束时,--last-value应为后续导入指定的值打印到屏幕上。在运行后续导入时,--last-value会指定上次的值以确保导入新的数据。这是增量导入自动处理的,这也是执行循环增量导入的首选机制。
Sqoop的导入工具的主要功能是将数据上传到HDFS中的文件中。如果Hive Metastore与HDFS集群相关联,则Sqoop还可以将数据导入到Hive中,并执行CREATE TABLE语句来定义Hive中的数据布局。将数据导入Hive中非常简单,只需要在命令中加入--hive-import参数即可。
如果Hive中表已经存在,可以使用--hive-overwrite参数指定要替换表。然后将数据导入HDFS或省略此步骤,Sqoop还将生成一个Hive脚本,其中包含CREATE TABLE语句和LOAD DATA INPATH语句。
脚本将在安装了Sqoop的机器上运行。如果安装了多个Hive,或者没有配置hive的环境变量$PATH,可以使用--hive-home参数来指定Hive的安装目录。Sqoop的$PATH一般为:$HIVE_HOME/bin/hive
注意:将数据导入到Hive中不能使用--as-avrodatafile和--assequencefile两种文件的存储方式。
如果数据库的数据内容包含Hive的缺省行分隔符(\n和\r字符)或列分隔符(\01字符)的字符串字段,则使用Sqoop将数据导入到Hive中时会遇到问题。
可以使用--hive-drop-import-delims选项在导入时删除这些字符,以保证数据与Hive的文本数据格式兼容。或者,可以使用该--hive-delims-replacement选项在导入时将这些字符替换为自定义的字符串,以保证数据与Hive的文本数据格式兼容。
使用Hive的默认分隔符时使用这两个参数。
如果使用--hive-import参数并没有设置分隔符,则使用Hive的默认分隔符:字段分隔符为^A,记录分隔符为\n。
Sqoop将默认导入NULL值作为字符串null。Hive使用字符串\N来表示NULL值,因此在将数据导入Hive中时NULL将无法被正确识别。
如果想要在数据导入Hive时正确地处理NULL,可以使用参数--null-string和--null-non-string。
如果想要在数据导出Hive时正确的处理NULL,可以使用参数--input-null-string和--input-null-non-string。
因为sqoop在生成的代码中需要使用这些参数,所以需要正确地将值转义\N为\\N:
$ sqoop import ... --null-string '\\N' --null-non-string '\\N'
Hive中使用的表名默认情况下与源表的名称相同。也可以使用--hive-table选项控制输出表名称。
Hive可以将数据放入分区以提高查询性能。Sqoop可以通过指定--hive-partition-key和--hive-partition-value参数将数据导入Hive的特定分区。分区值必须是一个字符串。有关分区的更多详细信息,请参阅Hive文档。
--compress和--compression-codec选项可以将数据压缩之后导入Hive中。
压缩导入到Hive中的表格的一个缺点是压缩的编码不能切分,从而导致不能并行mapper任务处理。
lzop编解码器支持分割。使用此压缩编解码器导入表格时,Sqoop将根据索引文件自动的对数据进行切分并创建正确的Hive表格式。此功能目前必须使用lzop编解码器对表的所有分区进行压缩。
Sqoop支持HDFS和Hive之外的其他导入目标。Sqoop同样也支持将数据导入HBase中的表中。
如果目标表和列族不存在,则Sqoop作业将退出并显示错误。在运行导入之前,应该创建目标表。
也可以使用--hbase-create-table参数,让Sqoop使用HBase配置中的默认参数创建目标表和列族(如果它们不存在)。
--hbase-table参数指定HBase接收数据的表。导入每一行的数据的操作都会转换为HBase Put操作。
每行的行键取自输入的一列,默认情况下,Sqoop将使用分隔列作为行键。如果没有指定分割列,它将使用源表的主键列(如果有的话)作为行键。
--hbase-row-key参数可以指定行键列。
如果导入的表具有联合主键,--hbase-row-key必须以逗号分隔联合主键。在这种情况下,HBase的行键将通过下划线分割联合主键的形式来生成。注意:只有--hbase-row-key在指定了参数的情况下,Sqoop才能正常导入具有联合主键的表。
--column-family参数指定列族,每个输出列将被放置在同一个列族中。
注意:此参数与direct模式导入(参数--direct)不兼容。
Sqoop将当前所有值序列化为HBase,方法是将每个字段转换为其字符串表示(就像在文本模式中导入HDFS一样),然后将此字符串的UTF-8字节插入到目标单元格中。Sqoop将跳过除行键列以外的所有列中包含空值的行。
--hbase-bulkload参数可以执行批量加载而不是直接写入,可以减轻HBase的负载。
Sqoop支持将数据导入Accumulo中。
由于本人对Accumulo这项技术不是很了解,此处暂时不做介绍,看官方文档的介绍和HBase差不多,这里只将参数列出,留待以后做补充。
用户可以通过修改配置文件conf/sqoop-site.xml来指定参数。参数可以像Hadoop配置文件中一样指定,例如:
<property>
<name>property.name</name>
<value>property.value</value>
</property>
也可以在命令行中使用通用参数指定,例如:
sqoop import -D property.name = property.value ...
以下应用示例说明如何在各种情况下使用导入工具。
从数据库导入表名为EMPLOYEES的表的数据:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES
数据库连接验证:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--username SomeUser -P
Enter password: (hidden)
选择导入的列:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--columns "employee_id,first_name,last_name,job_title"
控制并行导入(指定8个mappper):
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
-m 8
将数据存储在SequenceFiles中,并将生成的类名称设置为com.foocorp.Employee:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--class-name com.foocorp.Employee --as-sequencefile
指定分隔符:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--fields-terminated-by '\t' --lines-terminated-by '\n' \
--optionally-enclosed-by '\"'
导入数据到Hive中:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--hive-import
导入新增数据:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--where "start_date > '2010-01-01'"
指定分割列:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp --table EMPLOYEES \
--split-by dept_id
验证是否导入成功:
$ hadoop fs -ls EMPLOYEES
Found 5 items
drwxr-xr-x - someuser somegrp 0 2010-04-27 16:40 /user/someuser/EMPLOYEES/_logs
-rw-r--r-- 1 someuser somegrp 2913511 2010-04-27 16:40 /user/someuser/EMPLOYEES/part-m-00000
-rw-r--r-- 1 someuser somegrp 1683938 2010-04-27 16:40 /user/someuser/EMPLOYEES/part-m-00001
-rw-r--r-- 1 someuser somegrp 7245839 2010-04-27 16:40 /user/someuser/EMPLOYEES/part-m-00002
-rw-r--r-- 1 someuser somegrp 7842523 2010-04-27 16:40 /user/someuser/EMPLOYEES/part-m-00003
$ hadoop fs -cat EMPLOYEES/part-m-00000 | head -n 10
0,joe,smith,engineering
1,jane,doe,marketing
...
增量导入:
$ sqoop import --connect jdbc:mysql://db.foo.com/somedb --table sometable \
--where "id > 100000" --target-dir /incremental_dataset --append
使用validation对数据进行验证:
$ sqoop import --connect jdbc:mysql://db.foo.com/corp \
--table EMPLOYEES --validate
将关系型数据库导入数据到HDFS:
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 --table trade_detail \
--columns 'id, account, income, expenses'
指定输出路径、指定数据分隔符:
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 --table trade_detail \
--target-dir '/sqoop/td' --fields-terminated-by '\t'
指定Map数量 -m
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 --table trade_detail \
--target-dir '/sqoop/td1' --fields-terminated-by '\t' -m 2
增加where条件, 注意:条件必须用引号引起来
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 --table trade_detail \
--where 'id>3' --target-dir '/sqoop/td2'
增加query语句(使用 \ 将语句换行)
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 \
--query 'SELECT * FROM trade_detail where id > 2 AND $CONDITIONS' \
--split-by trade_detail.id --target-dir '/sqoop/td3'
注意:
如果使用--query这个命令的时候,需要注意的是where后面的参数,AND $CONDITIONS这个参数必须加上,而且存在单引号与双引号的区别,如果--query后面使用的是双引号,那么需要在$CONDITIONS前加上\即\$CONDITIONS。
如果设置map数量为1个时即-m 1,不用加上--split-by ${tablename.column},否则需要加上。
将关系型数据库导入数据到hive:
sqoop import --connect jdbc:mysql://192.168.1.10:3306/test \
--username root --password 123 --table person \
--hive-import --hive-table hivetab1 -m 1