之所以選擇Sqoop1是因為Sqoop2目前問題太多。無法正常使用,綜合比較后選擇Sqoop1。
Sqoop1安裝配置比較簡單
一、安裝部署
(1)、下載安裝包
下載地址:http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.5.2.tar.gz
解壓到/home/duanxz/sqoop
tar -zxvf sqoop-1.4.6-cdh5.5.2.tar.gz
(2)、拷貝mysql的jdbc驅動包mysql-connector-java-5.1.31-bin.jar到sqoop/lib目錄下。
duanxz@three:~/sqoop/sqoop-1.4.6-cdh5.5.2/lib$ ll mysql-connector-java-5.1.31.jar -rw------- 1 duanxz duanxz 964879 Jun 19 08:22 mysql-connector-java-5.1.31.jar duanxz@three:~/sqoop/sqoop-1.4.6-cdh5.5.2/lib$
(3)、配置環境變量
#sqoop export SQOOP_HOME=/home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2 export PATH="$PATH:$JAVA_HOME/bin:$HIVE_HOME/bin:$HIVE_HOME/conf:$SQOOP_HOME/bin"
(4)、復制sqoop/conf/sqoop-env-template.sh為sqoop-env.sh
添加相關的配置
#Set path to where bin/hadoop is available export HADOOP_COMMON_HOME=/usr/local/hadoop-2.7.6 #Set path to where hadoop-*-core.jar is available export HADOOP_MAPRED_HOME=/usr/local/hadoop-2.7.6 #set the path to where bin/hbase is available #export HBASE_HOME= #Set the path to where bin/hive is available export HIVE_HOME=/home/duanxz/hive/apache-hive-2.1.1-bin #Set the path for where zookeper config dir is #export ZOOCFGDIR=
(5)、測試Sqoop
sqoop help
結果:
duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$ sqoop help Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../hbase does not exist! HBase imports will fail. Please set $HBASE_HOME to the root of your HBase installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../hcatalog does not exist! HCatalog jobs will fail. Please set $HCAT_HOME to the root of your HCatalog installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../accumulo does not exist! Accumulo imports will fail. Please set $ACCUMULO_HOME to the root of your Accumulo installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../zookeeper does not exist! Accumulo imports will fail. Please set $ZOOKEEPER_HOME to the root of your Zookeeper installation. 18/06/19 18:20:23 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6-cdh5.5.2 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. duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$
說明:因為我們沒有基於hadoop安裝HBase,所以HBase相關的命令不能用,但是操作hadoop分布式文件系統的命令是可以用的。
再次執行sqoop version
duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$ sqoop version Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../hbase does not exist! HBase imports will fail. Please set $HBASE_HOME to the root of your HBase installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../hcatalog does not exist! HCatalog jobs will fail. Please set $HCAT_HOME to the root of your HCatalog installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../accumulo does not exist! Accumulo imports will fail. Please set $ACCUMULO_HOME to the root of your Accumulo installation. Warning: /home/duanxz/sqoop/sqoop-1.4.6-cdh5.5.2/../zookeeper does not exist! Accumulo imports will fail. Please set $ZOOKEEPER_HOME to the root of your Zookeeper installation. 18/06/19 18:55:22 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6-cdh5.5.2 Sqoop 1.4.6-cdh5.5.2 git commit id 8e266e052e423af592871e2dfe09d54c03f6a0e8 Compiled by jenkins on Mon Jan 25 16:10:15 PST 2016 duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$
二、使用Sqoop測試
2.1、測試連接:
(1)顯示mysql數據庫列表
sqoop list-databases --username risk_user --password 'risk_pwd' --connect jdbc:mysql://10.200.110.4:3306/risk_data?characterEncoding=UTF-8
(2)顯示數據庫里所有表:
sqoop list-tables --username risk_user --password 'risk_pwd' --connect jdbc:mysql://10.200.110.4:3306/risk_data?characterEncoding=UTF-8
2、Mysql與HDFS互導
(1)mysql導入到hdfs
mysql中創建一個測試表:
DROP TABLE IF EXISTS `user_info`; CREATE TABLE `user_info` ( `id` int(11) NOT NULL, `user_name` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `age` int(11) DEFAULT NULL, `address` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
加點數據:
insert into `user_info` (`id`, `user_name`, `age`, `address`) values('1','zhangsan ','20','shenzhen nanshang'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('2','lisi','21','shenzhen baoan'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('3','wangwu','23','shenzhen futian'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('4','zhuqi','25','shenzhen guangming'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('5','houba','26','shenzhen xili'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('6','cailiu','27','shenzhen xili'); insert into `user_info` (`id`, `user_name`, `age`, `address`) values('7','laojiu','27','shenzhen yantian');
把mysql中表user_info導入到hdfs,導入之前查詢一下user_info表中的數據
共:7條
sqoop import --connect jdbc:mysql://10.200.110.4:3306/risk_data --username risk_user --password 'risk_pwd' --table user_info --target-dir /tmp/hive/sqoop/user_info -m 4
參數說明:
-m:表示Map並發數
--target-dir:hdfs的目標目錄,若是不寫, 則默認是hdfs上的user/username/tablename 路徑
如果重復執行,會提示目錄已經存在,可以手動刪除
運行完mapreduce結束后去HDFS上檢查。
HDFS的50070上看到已經成功,如下圖:
驗證hdfs上導入的數據:
duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$ hadoop fs -ls /tmp/hive/sqoop/user_info Found 5 items -rw-r--r-- 1 duanxz supergroup 0 2018-06-19 19:14 /tmp/hive/sqoop/user_info/_SUCCESS -rw-r--r-- 1 duanxz supergroup 59 2018-06-19 19:14 /tmp/hive/sqoop/user_info/part-m-00000 -rw-r--r-- 1 duanxz supergroup 58 2018-06-19 19:14 /tmp/hive/sqoop/user_info/part-m-00001 -rw-r--r-- 1 duanxz supergroup 25 2018-06-19 19:14 /tmp/hive/sqoop/user_info/part-m-00002 -rw-r--r-- 1 duanxz supergroup 55 2018-06-19 19:14 /tmp/hive/sqoop/user_info/part-m-00003 duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$ hadoop fs -ls /tmp/hive/sqoop/user_info/part-m-00000 -rw-r--r-- 1 duanxz supergroup 59 2018-06-19 19:14 /tmp/hive/sqoop/user_info/part-m-00000 duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$ hadoop fs -cat /tmp/hive/sqoop/user_info/part-m-00000 1,zhangsan ,20,shenzhen nanshang 2,lisi,21,shenzhen baoan duanxz@ubuntu:~/sqoop/sqoop-1.4.6-cdh5.5.2/bin$
(2)HDFS導入到mysql
把HDFS中數據導入到Mysql表中,mysql中需要預先建立空表user_info2,此時該表為空
導入指令:
sqoop export --connect jdbc:mysql://10.200.110.4:3306/risk_data --table user_info2 -m 1 --username risk_user --password 'risk_pwd' --export-dir /tmp/hive/sqoop/user_info/ --input-fields-terminated-by ',' --columns="id,user_name,address"
運行完顯示
顯示導出7條記錄。
或者:根據條件篩選部分記錄導入到hdfs中。
sqoop import --connect jdbc:mysql://10.200.110.4:3306/risk_data --username risk_user --password 'risk_pwd' --query 'select id, user_name,age,address from user_info where $CONDITIONS LIMIT 100' --target-dir /tmp/hive/import/user_info --num-mappers 1 --fields-terminated-by ','
再到表user_info2查看
並且正好也是7條。
至此,用Sqoop將mysql與HDFS互導功都驗證完畢。
你還可以指定其他的參數:
參數 | 說明 |
---|---|
--append |
將數據追加到hdfs中已經存在的dataset中。使用該參數,sqoop將把數據先導入到一個臨時目錄中,然后重新給文件命名到一個正式的目錄中,以避免和該目錄中已存在的文件重名。 |
--as-avrodatafile |
將數據導入到一個Avro數據文件中 |
--as-sequencefile |
將數據導入到一個sequence文件中 |
--as-textfile |
將數據導入到一個普通文本文件中,生成該文本文件后,可以在hive中通過sql語句查詢出結果。 |
--boundary-query <statement> |
邊界查詢,也就是在導入前先通過SQL查詢得到一個結果集,然后導入的數據就是該結果集內的數據,格式如:--boundary-query 'select id,no from t where id = 3' ,表示導入的數據為id=3的記錄,或者 select min(<split-by>), max(<split-by>) from <table name> ,注意查詢的字段中不能有數據類型為字符串的字段,否則會報錯 |
--columns<col,col> |
指定要導入的字段值,格式如:--columns id,username |
--direct |
直接導入模式,使用的是關系數據庫自帶的導入導出工具。官網上是說這樣導入會更快 |
--direct-split-size |
在使用上面direct直接導入的基礎上,對導入的流按字節數分塊,特別是使用直連模式從PostgreSQL導入數據的時候,可以將一個到達設定大小的文件分為幾個獨立的文件。 |
--inline-lob-limit |
設定大對象數據類型的最大值 |
-m,--num-mappers |
啟動N個map來並行導入數據,默認是4個,最好不要將數字設置為高於集群的節點數 |
--query,-e <sql> |
從查詢結果中導入數據,該參數使用時必須指定–target-dir 、–hive-table ,在查詢語句中一定要有where條件且在where條件中需要包含 \$CONDITIONS ,示例:--query 'select * from t where \$CONDITIONS ' --target-dir /tmp/t –hive-table t |
--split-by <column> |
表的列名,用來切分工作單元,一般后面跟主鍵ID |
--table <table-name> |
關系數據庫表名,數據從該表中獲取 |
--delete-target-dir |
刪除目標目錄 |
--target-dir <dir> |
指定hdfs路徑 |
--warehouse-dir <dir> |
與 --target-dir 不能同時使用,指定數據導入的存放目錄,適用於hdfs導入,不適合導入hive目錄 |
--where |
從關系數據庫導入數據時的查詢條件,示例:--where "id = 2" |
-z,--compress |
壓縮參數,默認情況下數據是沒被壓縮的,通過該參數可以使用gzip壓縮算法對數據進行壓縮,適用於SequenceFile, text文本文件, 和Avro文件 |
--compression-codec |
Hadoop壓縮編碼,默認是gzip |
--null-string <null-string> |
可選參數,如果沒有指定,則字符串null將被使用 |
--null-non-string <null-string> |
可選參數,如果沒有指定,則字符串null將被使用 |
示例程序:
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --table TBLS --columns "tbl_id,create_time" --where "tbl_id > 1" --target-dir /user/hive/result
使用 sql 語句
參照上表,使用 sql 語句查詢時,需要指定 $CONDITIONS
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --query 'SELECT * from TBLS where \$CONDITIONS ' --split-by tbl_id -m 4 --target-dir /user/hive/result
上面命令通過 -m 1 控制並發的 map 數。
使用 direct 模式:
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --table TBLS --delete-target-dir --direct --default-character-set UTF-8 --target-dir /user/hive/result
指定文件輸出格式:
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --table TBLS --fields-terminated-by"\t" --lines-terminated-by "\n" --delete-target-dir --target-dir /user/hive/result
這時候查看 hdfs 中數據(觀察分隔符是否為制表符):
$ hadoop fs -ls result
Found 5 items -rw-r--r-- 3 root hadoop 0 2014-08-04 16:07 result/_SUCCESS -rw-r--r-- 3 root hadoop 69 2014-08-04 16:07 result/part-m-00000 -rw-r--r-- 3 root hadoop 0 2014-08-04 16:07 result/part-m-00001 -rw-r--r-- 3 root hadoop 142 2014-08-04 16:07 result/part-m-00002 -rw-r--r-- 3 root hadoop 62 2014-08-04 16:07 result/part-m-00003 $ hadoop fs -cat result/part-m-00000 34 1406784308 8 0 root 0 45 test1 EXTERNAL_TABLE null null null $ hadoop fs -cat result/part-m-00002 40 1406797005 9 0 root 0 52 test2 EXTERNAL_TABLE null null null 42 1407122307 7 0 root 0 59 test3 EXTERNAL_TABLE null null null
指定空字符串:
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --table TBLS --fields-terminated-by "\t" --lines-terminated-by "\n" --delete-target-dir --null-string '\\N' --null-non-string '\\N' --target-dir /user/hive/result
如果需要指定壓縮:
$ sqoop import --connect jdbc:mysql://192.168.56.121:3306/metastore --username hiveuser --password redhat --table TBLS --fields-terminated-by "\t" --lines-terminated-by "\n" --delete-target-dir --null-string '\\N' --null-non-string '\\N' --compression-codec "com.hadoop.compression.lzo.LzopCodec" --target-dir /user/hive/result
附:可選的文件參數如下表。
參數 | 說明 |
---|---|
--enclosed-by <char> |
給字段值前后加上指定的字符,比如雙引號,示例:--enclosed-by '\"' ,顯示例子:"3","jimsss","dd@dd.com" |
--escaped-by <char> |
給雙引號作轉義處理,如字段值為"測試",經過 --escaped-by "\\" 處理后,在hdfs中的顯示值為:\"測試\" ,對單引號無效 |
--fields-terminated-by <char> |
設定每個字段是以什么符號作為結束的,默認是逗號,也可以改為其它符號,如句號. ,示例如:--fields-terminated-by |
--lines-terminated-by <char> |
設定每條記錄行之間的分隔符,默認是換行串,但也可以設定自己所需要的字符串,示例如:--lines-terminated-by "#" 以#號分隔 |
--mysql-delimiters |
Mysql默認的分隔符設置,字段之間以, 隔開,行之間以換行\n 隔開,默認轉義符號是\ ,字段值以單引號' 包含起來。 |
--optionally-enclosed-by <char> |
enclosed-by是強制給每個字段值前后都加上指定的符號,而--optionally-enclosed-by 只是給帶有雙引號或單引號的字段值加上指定的符號,故叫可選的 |
3、Mysql與Hive互導
下面的命令行,將mysql的user_info表導入到hive的
sqoop import --connect jdbc:mysql://10.200.110.4:3306/risk_data --table user_info --username risk_user --password 'risk_pwd' --fields-terminated-by ',' --delete-target-dir --num-mappers 1 --hive-import --hive-database default --hive-table hive_user_info
出現如下錯誤:
錯誤1:Sqoop:Import failed: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
解決方法:
將mysql中的數據導入到hive中報錯:
這是因為sqoop需要一個hive的包,將hive/lib中的hive-common-2.3.3.jar拷貝到sqoop的lib目錄中,重新執行試試。
錯誤2:ERROR tool.CreateHiveTableTool: Encountered IOException running create table job: java.io.IOException: Hive exited with status 1
解決方法:
我的hive是本地模式,只能一個用戶登錄。所以要把另外一個hive登錄給退出。
錯誤3:error='Cannot allocate memory' (errno=12)
解決方法:
我的hive是本地模式,只能一個用戶登錄。所以要把另外一個hive登錄給退出。
錯誤4:Version information not found ,Caused by: MetaException(message:Version information not found in metastore. )
解決方法:
1、mysql-connector-java-5.1.26-bin.jar 是否放到hive/lib 目錄下 建議修改權限為777 (chmod 777 mysql-connector-java-5.1.26-bin.jar)
2、修改conf/hive-site.xml 中的 “hive.metastore.schema.verification” 值為 false 即可解決 “Caused by: MetaException(message:Version information not found in metastore. )”
錯誤3:
ERROR tool.ImportTool: EncounteredIOException running import job: java.io.IOException: DataStreamer Exception:
atorg.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:796)
Caused by: java.lang.OutOfMemoryError:unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
atorg.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.initDataStreaming(DFSOutputStream.java:581)
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:669)
解決方法:
net.ipv4.ip_local_port_range = 1024 65000
修改系統參數
echo "100000" > /proc/sys/kernel/threads-max |
echo "100000" > /proc/sys/kernel/pid_max (默認32768) |
echo "200000" > /proc/sys/vm/max_map_count (默認65530) |
修改/etc/security/limits.conf
* - nproc 999999
* -nofile 999999
PS:nproc是修改系統的max user processes大小;nofile 是修改open files的大小,另外linux 2.6.25內核之前有個宏定義,定義了這個值的最大值,為1024*1024,正好是100萬,而在2.6.25內核及其之后,這個值是可以通過/proc/sys/fs/nr_open來設置,不過,999999足夠用了。
很多人可能會遇到,只能啟動32000多個線程就不能再起更多的線程了,其實就是pid_max = 32768 給限制住了
增加map數量,通過sqoop -m 選項指定更多的map。通過更多的map,降少每個子進程占用的heap space,避免超出hadoop設置的java heap space 大小
sqoop ... -m <map 數量>
錯誤2:
Caused by: java.lang.RuntimeException:java.sql.SQLException: Access denied for user 'root'@'hadoop003' (usingpassword: YES)
atorg.apache.sqoop.mapreduce.db.DBInputFormat.getConnection(DBInputFormat.java:220)
atorg.apache.sqoop.mapreduce.db.DBInputFormat.setConf(DBInputFormat.java:165)
... 9 more
程序正常運行,結果也正確。說明數據庫連接是正確的,而且單獨用mysql連接也是可以的。就是報這個異常錯誤。
查詢數據庫里用戶信息
JDBC連接的機器名是hadoop003,雖然已經賦予root所有機器的遠程訪問權限(“%”),但是hadoop003這個賬戶可能沒有開通機器的遠程權限。於是給hadoop003這個機器開通遠程權限。
GRANT ALL PRIVILEGES ON *.* TO'root'@'hadoop003' IDENTIFIED BY '********' WITH GRANT OPTION;
再次執行導入命令。成功。不再出現上面錯誤。
錯誤3:
從mysql導入到Hive里報如下錯誤:
ERROR hive.HiveConfig: Could not loadorg.apache.hadoop.hive.conf.HiveConf. Make sure HIVE_CONF_DIR is set correctly.
16/02/26 14:43:47 ERROR tool.ImportTool:Encountered IOException running import job: java.io.IOException:java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
數據已經導入到HDFS。從HDFS移動到Hive里時出錯。提示HIVE_CONF_DIR配置不對。
但是將HIVE_CONF_DIR添加到sqoop-env.sh、hadoop-env.sh、hive-env.sh都不起作用。
最終正確的解決方法:
在/etc/profile 里添加下面一句話
exportHADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HIVE_HOME/lib/*
Sqoop-1.4.7版本好像解決了這個問題。期待這個版本