最近在負責公司的數據倉庫遷移以及重構的工做,主要是Hadoop集羣之間的數據遷移和從新拉去線上Oracle數據庫中數據到Hadoop集羣來支撐數據倉庫。其中Hadoop集羣中數據遷移是使用Linux中Distcp來進行批量遷移,對於Oracle到Hadoop的這一解決方案使用的是Sqoop工具(淘寶的數據遷移工具DataX聽說不錯,可是沒有實際的操做過),那麼對於RDBMS到HDFS的解決方案,熟悉Hadoop技術棧的應該都會首先想到Sqoop,由於操做簡單,不用寫代碼,腳本命令行的方式就能夠實現大量以及多數據源的遷移工做(若是你精力充沛,能夠嘗試寫spark^_^)html
兩年前,用sqoop作過CSV和SQLServer導入Hive,那次實施只是將已有的數據全量import到Hive,並且數據量不大單表900M左右,因此Hive端並不用作分區。
而如今,拉取的是天天不斷生成的線上數據,而且要根據時間dt和產品product_id作兩個分區,避免在Hive Select查詢掃描整個表,消耗時間。有時候只須要掃描表中關心的一部分數據,就是由於用sqoop向Hive分區表寫數據的時候我踩了不少坑,因此決定要寫博客來回饋社會數據庫
環境:
sqoop 1.4.6
Hadoop 2.7.2
Oracle 11g網絡
確保所要進行鏈接的數據庫驅動 ojdbc6.jar 是在SQOOP_HOME/lib目錄下
下載地址http://www.oracle.com/technet...數據結構
sqoop list-tables --driver oracle.jdbc.driver.OracleDriver --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd
鏈接成功的話,會打印出庫中的表
注:鏈接Oracle,用戶名和密碼都要大寫oracle
(1)能夠先用sqoop打印出oracle中要向Hive中導入的表結構和數據結構,用下面的命令:app
sqoop eval --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --query "SELECT * FROM TABLENAME WHERE rownum<=2 \$CONDITIONS"
(2)根據業務需求,建立的Hive表有要求是一個partition,有要求是兩個partition的,partition的不一樣,使用的sqoop導入語句是不一樣的。tcp
單分區表
建立表工具
CREATE TABLE tablename ( field1 string, field2 tinyint, ....... fieldn string) PARTITIONED BY (dt string) STORED AS AVRO TBLPROPERTIES ('avro.compress'='snappy')
建立的Hive表採用Avro格式,而且使用snappy壓縮,節省空間而且格式靈活能夠擴充字段
建立完畢,使用下面的命令導入數據oop
sqoop import --hive-import --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --table oracletablename --columns field1,...,fieldn --where "fieldn='xxx'" --hive-database hivedatabasename --hive-table hivetablename --hive-partition-key dt --hive-partition-value partitionName --split-by fieldn -m 6
上面這條語句,須要你們注意的是:
--table 參數所接的oracle庫名要大寫
--columns 所選出的字段要匹配Hive表中對應的字段
--where 後面接的條件至關於 select語句中的where條件,對抽出來的數據作篩選,也可使用--query "SQL"來實現數據篩選
--split-by 着重說明,須要填寫一個columns中的字段對查詢出來的數據集作分片,最好填寫一個數值型字段,不然須要添加其餘配置參數(很麻煩的)
-m 指定map任務的數量,將上面的數據集按照 -m 後面的數字進行等量切分測試
雙分區表
建立表
hcat -e "create table tablename (field1 string.....fieldn string) partitioned by (dt string,pid string) STORED AS AVRO TBLPROPERTIES ('avro.compress'='snappy') "
導入語句
sqoop import --hive-import --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --table oracletablename --columns field1,...,fieldn --where "field_Time>=TO_DATE('2017-12-01 10:44:02','yyyy-mm-dd hh24:mi:ss')" --hcatalog-database "hivedatabaseName" --hcatlog-table hivetableName --hcatalog-partition-keys dt,pid --hcatalog-partition-values "2017-01-01","pidName" --split-by fieldn -m 6
爲何 --hive-table partition key and value在 這裏要換成 --hcatlog-table key and value呢?
由於,--hive-table中,只支持一個靜態分區,仔細的研讀sqoop官網,你會發現--hcatlog-table支持多個靜態分區
至此,按照個人步驟和參數的規範,你就能夠順利的應對多種狀況了。
不過在每一個人的開發過程當中,確定會遇到不一樣的坑和錯誤
可能會遇到的問題
hadoop集羣與oracle環境的網絡鏈接容許。
使用--query或者--where時遇到 SQLException :00933錯誤 這樣你就要注意你的SQL語句是否正確,致使這個錯誤的還多是其餘緣由,詳情查看官網
map階段一直卡住,多是你單次拉取數據量過大,若是數據量太大,必定要對數據進行篩選後進行導入
懂得分享 回饋社會