(轉) Sqoop使用實例講解


原博客地址:http://blog.csdn.net/evankaka

 

  摘要:本文主要講了筆者在使用sqoop過程中的一些實例

一、概述與基本原理

         Apache Sqoop(SQL-to-Hadoop) 項目旨在協助 RDBMS 與 Hadoop 之間進行高效的大數據交流。用戶可以在 Sqoop 的幫助下,輕松地把關系型數據庫的數據導入到 Hadoop 與其相關的系統 (如HbaseHive)中;同時也可以把數據從 Hadoop 系統里抽取並導出到關系型數據庫里。因此,可以說Sqoop就是一個橋梁,連接了關系型數據庫與Hadoop。qoop中一大亮點就是可以通過hadoop的mapreduce把數據從關系型數據庫中導入數據到HDFS。Sqoop架構非常簡單,其整合了Hive、Hbase和Oozie,通過map-reduce任務來傳輸數據,從而提供並發特性和容錯。Sqoop的基本工作流程如下圖所示:

從關系數據庫到Hive/hbase
從Hive/hbase到關系數據庫


  Sqoop在import時,需要制定split-by參數。Sqoop根據不同的split-by參數值來進行切分,然后將切分出來的區域分配到不同map中。每個map中再處理數據庫中獲取的一行一行的值,寫入到HDFS中(由此也可知,導入導出的事務是以Mapper任務為單位)。同時split-by根據不同的參數類型有不同的切分方法,如比較簡單的int型,Sqoop會取最大和最小split-by字段值,然后根據傳入的num-mappers來確定划分幾個區域。 比如select max(split_by),min(split-by) from得到的max(split-by)和min(split-by)分別為1000和1,而num-mappers為2的話,則會分成兩個區域(1,500)和(501-100),同時也會分成2個sql給2個map去進行導入操作,分別為select XXX from table where split-by>=1 and split-by<500和select XXX from table where split-by>=501 and split-by<=1000。最后每個map各自獲取各自SQL中的數據進行導入工作。

 

二、使用實例

接下來將以實例來說明如何使用

1、創建表

sqoop可以將MySQL表或其它關系型數據庫的表結構自動映射到Hive表。映射后的表結構為textfile格式。先來看一個腳本

#!/bin/sh  
. ~/.bashrc  
  
host='xx.xx.xx.xx'  
database='cescore'  
user='xxxx'  
password='xxxx'  
mysqlTable='yyyyyyy'  
hiveDB='ods_uba'  
hiveTable='yyyyyy'  
  
sqoop create-hive-table \  
--connect jdbc:mysql://${host}:3306/${database} --username ${user} --password ${password} \  
--table ${mysqlTable} \  
--hive-table ${hiveDB}.${hiveTable} \  
--hive-overwrite  --hive-partition-key req_date \  
  
rm *.java  

--connect 指明連接的類型,基本所有的關系型數據庫都可以

--table 指明要源表的表名

--hive-table 指明要創建的Hive表名

--hive-overwrite 指明是否覆蓋插入(將原來的分區數據全刪除,再插入)

--hive-partition-key 指明分區的字段

我們可以到Hive去查看對應的表結構:

 

 

2、從mysql導數據到Hive

sqoop可以將數據從關系型數據庫導到Hive或Hive導到關系型數據庫,先來看一個從mydql導數據到Hive的實例,示例腳本如下

先來看一個腳本

#!/bin/sh  
. ~/.bashrc  
  
host='xx.xx.xx.xx'  
database='xxxcc'  
user='xxxx'  
password='xxxx'  
mysqlTable='sys_approve_reject_code'  
hiveDB='ods_uba'  
hiveTable='sys_approve_reject_code'  
tmpDir='/user/hive/warehouse/ods_uba.db/'${hiveTable}  
  
sqoop import --connect jdbc:mysql://${host}:3306/${database} --username ${user} --password ${password} \  
--query "select * from "${database}"."${mysqlTable}" where 1 = 1 and \$CONDITIONS" \  
--hive-import --hive-table ${hiveDB}.${hiveTable} --target-dir ${tmpDir} --delete-target-dir --split-by approve_reject_code \  
--hive-overwrite \  
--null-string '\\N' --null-non-string '\\N'  

 一般情況下,如果Hive里的表不存在,也可以不用執行第一步的創建表的步驟,因為一般導數時,它如果發現hive表不存在,會自己幫你創建表,Hive表的數據結構就和mysql的一樣。不過,這樣要注意一個點,如果Hive表是你自己通過Hive的交互命令行建立起來的,並且存儲格式設置為orc,那么使用sqoop導數據到這個表時是可以導入成功,但是會發現無法查詢出來,或者查詢亂碼。只能設置成textfile才可以。

     上面的sql是將表全量導入到Hive中,不進行分區操作,每次導數都會將原來的數據刪除,因為這是一張字典表,所以需要這么做。來看看各字段的含義

--query 指明查詢的sql語句,注意主里加了一個 and \$conditions ,這是必需的,如果有帶where條件的話

--hive-table 指明目標表名

--target-dir 指明目標表的hdfs路徑

--delete-target-dir 刪除目標hfds路徑數據

--split-by 指明shuffle的字段,一般是取主鍵

--hive-overwrite 先刪除舊數據,再重新插入

--null-string --對null字符串和處理,映射成hive里的null

--null-non-string --對null非字符串和處理,映射成hive里的null

3、從phoenix導數據到Hive

下面再來看一個比較復雜的腳本,這里將從phoenix導數據,並將一天的數據分成24份

#!/bin/sh  
. ~/.bashrc  
  
#導數據,注意要傳入一個yyyy-mm-dd類型參數  
synData(){  
  echo "您要統計數據的日期為:$statisDate"  
  #生成每小時的查詢條件  
  for i in `seq 24`  
  do  
    num=$(echo $i)  
    doSqoop $statisDate $num  
  done  
}  
  
#sqoop導數據  
doSqoop(){  
    echo "輸入日期:$statisDate,輸入序列號:$num"  
    timeZone=$(printf "%02d\n" $(expr "$num" - "1"))   
    partitionTime=$(echo "$statisDate-$timeZone")  
    evtNOPre=$(echo $partitionTime | sed 's/\-//g')  
    echo "分區字段:$partitionTime"  
    where_qry=$(echo "evt_no like '$evtNOPre%'")  
    echo $where_qry  
     
   hiveDB='ods_uba'  
   hiveTable='evt_log'  
   tmpDir='/user/hive/warehouse/ods_uba.db/'${hiveTable}  
  
   sqoop import -D mapreduce.map.memory.mb=3072 --driver org.apache.phoenix.jdbc.PhoenixDriver \  
   --connect jdbc:phoenix:xxxxxxxx \  
   --query "select * from uba.evt_log  where $where_qry  and \$CONDITIONS" \  
   --hive-import --hive-table ${hiveDB}.${hiveTable} --target-dir ${tmpDir} --delete-target-dir --split-by evt_no \  
   --hive-overwrite  --hive-partition-key partition_time --hive-partition-value ${partitionTime} \  
   --null-string '\\N' --null-non-string '\\N'  
   rm *.java  
   
}  
  
#統計日期默認取昨天  
diffday=1  
statisDate=`date +"%Y-%m-%d" -d "-"${diffday}"day"`  
#首先判斷是否有輸入日期,以及輸入日期是否合法,如果合法,取輸入的日期。不合法報錯,輸入日期為空,取昨天  
if [ $# -eq 0 ]; then  
  echo "您沒有輸入參數"   
  synData $statisDate  
elif [ $# -eq 1 ]; then  
  echo "您輸入參數為: $1 "  
  statisDate=$1  
  if [ ${#statisDate} -eq 10 ];then  
     synData $statisDate  
  else  
     echo "您輸入日期不合法,請輸入yyyy-mm-dd類型參數"  
  fi  
else  
  echo "您輸入參數多於一個,請不要輸入或只輸入一個yyyy-mm-dd類型參數"  
fi  

-D mapreduce.map.memory.mb=3072,這是一個非常有用的參數,一般如果數據量非常大,在抽數據時有可能報內存不足,這時可以通過調高這個參數。

--driver 這里指明了使用的驅動類型,注意要將對應的驅動連接包放到sqoop對應的lib目錄下,要不會報錯

--hive-partition-key 指明分區字段

--hive-partition-value 指明分區值

這里因為是每天抽數,所以按天進行分區,因為還將每天分成了24個小時,理論上講設置成兩個分區字段會好點,但是sqoop只支持設置一個分區字段,所以這里的分區字段會被設計成yyyy-mm-dd-hh的類型

4、從mysql到hbse

sqoop import --connect jdbc:mysql://localhost/acmedb \  
--table ORDERS --username test --password **** \  
--hbase-create-table --hbase-table ORDERS --column-family mysql  

--hbase-create-table: 指明使用sqoop創建hbse表
--hbase-table: hbase表
--column-family: --指明列族,將所有的mysql的列都放在這個列族下面


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM