日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Hadoop和关系型数据库间的数据传输工具——Sqoop

發(fā)布時間:2023/12/20 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hadoop和关系型数据库间的数据传输工具——Sqoop 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Hadoop和關系型數(shù)據(jù)庫間的數(shù)據(jù)傳輸工具——Sqoop

一、Sqoop簡介以及使用

1.1、產(chǎn)生背景

基于傳統(tǒng)關系型數(shù)據(jù)庫的穩(wěn)定性,還是有很多企業(yè)將數(shù)據(jù)存儲在關系型數(shù)據(jù)庫中;早期由于工具的缺乏,Hadoop與傳統(tǒng)數(shù)據(jù)庫之間的數(shù)據(jù)傳輸非常困難。基于前兩個方面的考慮,需要一個在傳統(tǒng)關系型數(shù)據(jù)庫和Hadoop之間進行數(shù)據(jù)傳輸?shù)捻椖?#xff0c;Sqoop應運而生。

1.2、Sqoop是什么

Sqoop是一個用于Hadoop結構化數(shù)據(jù)存儲(如關系型數(shù)據(jù)庫)之間進行高效傳輸大批量數(shù)據(jù)的工具。它包括以下兩個方面:

  • 可以使用Sqoop將數(shù)據(jù)從關系型數(shù)據(jù)庫管理系統(tǒng)(如MySQL)導入到Hadoop系統(tǒng)(如HDFS、Hive、HBase)中
  • 將數(shù)據(jù)從Hadoop系統(tǒng)中抽取并導出到關系型數(shù)據(jù)庫(如MySQL)

常見數(shù)據(jù)庫開源工具:

  • sqoop
  • datax
  • kettle
  • cannal
  • 1.3、底層實現(xiàn)原理

    ? Sqoop的核心設計思想是利用MapReduce加快數(shù)據(jù)傳輸速度。也就是說Sqoop的導入和導出功能是通過基于Map Task(只有map)的MapReduce作業(yè)實現(xiàn)的。所以它是一種批處理方式進行數(shù)據(jù)傳輸,難以實現(xiàn)實時的數(shù)據(jù)進行導入和導出。


    官網(wǎng)介紹:
    Apache Sqoop? is a tool designed for efficiently transferring bulk
    data between Apache Hadoop and structured datastores such as relational databases.

    Sqoop結構圖:

    1.4、特點

    • 優(yōu)點:它可以將跨平臺的數(shù)據(jù)進行整合。
    • 缺點:它不是很靈活。

    主要執(zhí)行操作

    #mermaid-svg-GlkoSBcpbHzyZ0FK {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .error-icon{fill:#552222;}#mermaid-svg-GlkoSBcpbHzyZ0FK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GlkoSBcpbHzyZ0FK .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-GlkoSBcpbHzyZ0FK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GlkoSBcpbHzyZ0FK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GlkoSBcpbHzyZ0FK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GlkoSBcpbHzyZ0FK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GlkoSBcpbHzyZ0FK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .marker.cross{stroke:#333333;}#mermaid-svg-GlkoSBcpbHzyZ0FK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GlkoSBcpbHzyZ0FK .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GlkoSBcpbHzyZ0FK text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GlkoSBcpbHzyZ0FK .actor-line{stroke:grey;}#mermaid-svg-GlkoSBcpbHzyZ0FK .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .sequenceNumber{fill:white;}#mermaid-svg-GlkoSBcpbHzyZ0FK #sequencenumber{fill:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .messageText{fill:#333;stroke:#333;}#mermaid-svg-GlkoSBcpbHzyZ0FK .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GlkoSBcpbHzyZ0FK .labelText,#mermaid-svg-GlkoSBcpbHzyZ0FK .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GlkoSBcpbHzyZ0FK .loopText,#mermaid-svg-GlkoSBcpbHzyZ0FK .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GlkoSBcpbHzyZ0FK .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GlkoSBcpbHzyZ0FK .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GlkoSBcpbHzyZ0FK .noteText,#mermaid-svg-GlkoSBcpbHzyZ0FK .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GlkoSBcpbHzyZ0FK .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GlkoSBcpbHzyZ0FK .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GlkoSBcpbHzyZ0FK .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GlkoSBcpbHzyZ0FK .actorPopupMenu{position:absolute;}#mermaid-svg-GlkoSBcpbHzyZ0FK .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GlkoSBcpbHzyZ0FK .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GlkoSBcpbHzyZ0FK .actor-man circle,#mermaid-svg-GlkoSBcpbHzyZ0FK line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GlkoSBcpbHzyZ0FK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}MysqlHDFSHiveHBaseimportimportimportexportexportMysqlHDFSHiveHBase

    sqoop的重要的幾個關鍵詞

    • import : 從關系型數(shù)據(jù)庫到hadoop
    • export : 從hadoop到關系型數(shù)據(jù)庫。

    二、Sqoop的安裝

    注意:在安裝sqoop之前要配置好本機的Java環(huán)境和Hadoop環(huán)境

    先把spoop的安裝包sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz拷貝在系統(tǒng)目錄下的 /root/soft下面

    2.1、解壓配置環(huán)境變量

    # 解壓tar.gz包 [root@master local] tar -zxvf /root/sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /usr/local/#把sqoop的安裝路徑修改為sqoop,方便以后配置和調用 [root@master local]# mv sqoop-1.4.7.bin__hadoop-2.6.0 sqoop [root@master sqoop]# vim /etc/profile # 追加內(nèi)容如下:export SQOOP_HOME=/usr/local/sqoop export PATH=$SQOOP_HOME/bin:$PATH

    2.2、新建配置文件

    [root@master sqoop] mv ./conf/sqoop-env-template.sh ./conf/sqoop-env.sh

    2.3、修改配置文件

    配置文件:

    [root@master sqoop] vim ./conf/sqoop-env.sh

    按照本系統(tǒng)實際安裝的Hadoop系列目錄配置好下面的路徑:

    export HADOOP_COMMON_HOME=/usr/local/hadoop export HADOOP_MAPRED_HOME=/usr/local/hadoop export HIVE_HOME=/usr/local/hive export ZOOCFGDIR=/usr/local/zookeeper

    2.4、拷貝mysql驅動

    因為我們現(xiàn)在通過JDBC讓Mysql和HDFS等進行數(shù)據(jù)的導入導出,所以我們先必須把JDBC的驅動包拷貝到sqoop/lib路徑下,如下

    [root@master sqoop] cp /root/mysql-connector-java-5.1.18.jar ./lib/

    2.5、驗證安裝:

    #查看sqoop的版本 [root@master sqoop] sqoop version

    三、Sqoop命令執(zhí)行

    3.1、常見命令執(zhí)行參數(shù)

    通過sqoop加不同參數(shù)可以執(zhí)行導入導出,通過sqoop help 可以查看常見的命令行

    #常見sqoop參數(shù) [root@master sqoop] sqoop helpcodegen Generate code to interact with database recordscreate-hive-table Import a table definition into Hiveeval Evaluate a SQL statement and display the resultsexport Export an HDFS directory to a database table #導出help List available commandsimport Import a table from a database to HDFS #導入import-all-tables Import tables from a database to HDFSimport-mainframe Import mainframe datasets to HDFSlist-databases List available databases on a serverlist-tables List available tables in a databaseversion Display version information

    3.2、直接執(zhí)行命令

    Sqoop運行的時候不需要啟動后臺進程,直接執(zhí)行sqoop命令加參數(shù)即可.簡單舉例如下:

    # #通過參數(shù)用下面查看數(shù)據(jù)庫 [root@master sqoop] sqoop list-databases --connect jdbc:mysql://node2:3306 --username root --password 123123;

    3.3、通過文件傳遞參數(shù)(腳本)

    在執(zhí)行sqoop命令時,如果每次執(zhí)行的命令都相似,那么把相同的參數(shù)可以抽取出來,放在一個文本文件中,把執(zhí)行時的參數(shù)加入到這個文本文件為參數(shù)即可. 這個文本文件可以用--options-file來指定,平時可以用定時任務來執(zhí)行這個腳本,避免每次手工操作.

    3.2章節(jié)中命令中的jdbc連接的參數(shù)一般是不變的,可以把它抽取出來放在一個文件中/.../sqoop/config.conf,如下:

    list-databases --connect jdbc:mysql://localhost:3306 --username root --password 123123

    那么上面的執(zhí)行的命令就可以變?yōu)?

    [root@master sqoop] bin/sqoop --options-file config.conf

    為了讓配置文件config.txt的可讀性更強,可以加入空行和注釋,不會影響文件內(nèi)容的讀取,如下:

    # 指令: 列出mysql中的所有數(shù)據(jù)庫 list-databases# 指定連接字符串 --connect jdbc:mysql://localhost:3306--username root--password 123123

    3.4、Import 詳解

    import是從關系數(shù)據(jù)庫導入到Hadoop,下面是一些通用參數(shù)介紹:

    3.4.1、通用參數(shù)

    如下:

    ArgumentDescription
    –connect指定JDBC連接字符串
    --connection-manager 指定連接管理類
    --driver 指定連接的驅動程序
    -P從控制臺讀入密碼(可以防止密碼顯示中控制臺)
    –password指定訪問數(shù)據(jù)庫的密碼
    –username指定訪問數(shù)據(jù)庫的用戶名

    3.4.1.1、連接數(shù)據(jù)庫

    sqoop的設計就是把數(shù)據(jù)庫數(shù)據(jù)導入HDFS,所以必須指定連接字符串才能訪問數(shù)據(jù)庫,這個連接字符串類似于URL,這個連接字符串通過--connect參數(shù)指定,它描述了連接的數(shù)據(jù)庫地址和具體的連接數(shù)據(jù)庫,譬如:

    #指定連接的服務器地址是database.example.com ,要連接的數(shù)據(jù)庫是employees [root@master sqoop] sqoop import --connect jdbc:mysql://database.example.com/employees

    上面連接命令只是指定數(shù)據(jù)庫,默認情況下數(shù)據(jù)庫都是需要用戶名和參數(shù)的,在這里可以用--username 和--password來指定,譬如:

    #指定用戶名和密碼來連接數(shù)據(jù)庫 [root@master sqoop] sqoop import --connect jdbc:mysql://localhost:3306/mysql --username root --password 123123;

    3.4.1.2、查看數(shù)據(jù)庫

    在Sqoop中,可以通過list-databases參數(shù)來查看mysql的數(shù)據(jù)庫,這樣在導入之前可以得到所有的數(shù)據(jù)庫的名字,具體案例如下:

    # 列出所有數(shù)據(jù)庫 [root@master sqoop] bin/sqoop list-databases --connect jdbc:mysql://localhost:3306 --username root --password 123123;

    3.4.1.3、查看所有表

    在得到所有數(shù)據(jù)庫的名字后,也可以查看當前數(shù)據(jù)庫中的所有表,可以使用 list-tables參數(shù)來進行查看,查看的時候在url連接中一定要指定數(shù)據(jù)庫的名字.

    # 列出數(shù)據(jù)庫中所有表 [root@master sqoop] bin/sqoop list-tables --connect jdbc:mysql://node2:3306/qfdb --username root --password 123123;

    3.4.2、Import的控制參數(shù)

    常見Import的控制參數(shù)有如下幾個:

    ArgumentDescription
    --append通過追加的方式導入到HDFS
    --as-avrodatafile導入為 Avro Data 文件格式
    --as-sequencefile導入為 SequenceFiles文件格式
    --as-textfile導入為文本格式 (默認值)
    --as-parquetfile導入為 Parquet 文件格式
    --columns 指定要導入的列
    --delete-target-dir如果目標文件夾存在,則刪除
    --fetch-size 一次從數(shù)據(jù)庫讀取的數(shù)量大小
    -m,--num-mappers n 用來指定map tasks的數(shù)量,用來做并行導入
    -e,--query 指定要查詢的SQL語句
    --split-by 用來指定分片的列
    --table 需要導入的表名
    --target-dir HDFS 的目標文件夾
    --where 用來指定導入數(shù)據(jù)的where條件
    -z,--compress是否要壓縮
    --compression-codec 使用Hadoop壓縮 (默認是 gzip)

    3.4.2.1、指定表導入

    數(shù)據(jù)準備

    在本地mysql數(shù)據(jù)庫中新建一個qfdb數(shù)據(jù)庫,sql代碼在data/qfdb.sql中,如下:

    CREATE TABLE emp(empno INT primary key,ename VARCHAR(50),job VARCHAR(50),mgr INT,hiredate DATE,sal DECIMAL(7,2),comm decimal(7,2),deptno INT ) ; INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30); INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30); INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20); INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30); INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30); INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10); INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20); INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10); INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30); INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20); INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30); INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20); INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);

    sqoop的典型導入都是把關系數(shù)據(jù)庫中的表導入到HDFS中,使用--table參數(shù)可以指定具體的表導入到hdfs,譬如用 --table emp,默認情況下是全部字段導入.如下:

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp \ --target-dir hdfs://master:9000/sqoopdata/emp --delete-target-dir

    可以快速使用hdfs的命令查詢結果

    [root@master sqoop]# hdfs dfs -cat /sqoopdata/emp/par*

    3.4.2.2、指定列導入

    如果想導入某幾列,可以使用 --columns,如下:

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp \ --columns 'empno,mgr' \ --target-dir hdfs://master:9000/sqoopdata/emp \ --delete-target-dir

    可以使用下面hdfs命令快速查看結果

    [root@master sqoop]# hdfs dfs -cat /sqoopdata/emp/par*

    3.4.2.3、指定條件導入

    在導入表的時候,也可以通過指定where條件來導入,具體參數(shù)使用 --where,譬如要導入員工號大于7800的記錄,可以用下面參數(shù):

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp \ --columns 'empno,mgr' \ --where 'empno>7800' \ --target-dir hdfs://master:9000/sqoopdata/5 \ --delete-target-dir

    用命令查詢結果:

    [root@master sqoop]# hdfs dfs -cat /sqoopdata/emp/par*

    結果如下:

    7839,null 7844,7698 7876,7788 7900,7698 7902,7566 7934,7782

    3.4.2.4、指定Sql導入

    上面的可以通過表,字段,條件進行導入,但是還不夠靈活,其實sqoop還可以通過自定義的sql來進行導入,可以通過--query 參數(shù)來進行導入,這樣就最大化的用到了Sql的靈活性。如下:

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --query 'select empno,mgr,job from emp WHERE empno>7800 and $CONDITIONS' \ --target-dir hdfs://master:9000/sqoopdata/emp \ --delete-target-dir \ --split-by empno \ -m 1

    注意:在通過--query來導入數(shù)據(jù)時,必須要指定--target-dir

    如果你想通過并行的方式導入結果,每個map task需要執(zhí)行sql查詢語句的副本,結果會根據(jù)sqoop推測的邊界條件分區(qū)。query必須包含$CONDITIONS。這樣每個scoop程序都會被替換為一個獨立的條件。同時你必須指定--split-by。分區(qū) -m 1 是指定通過一個Mapper來執(zhí)行流程

    查詢執(zhí)行結果

    [root@master sqoop]# hdfs dfs -cat /sqoopdata/emp/par*

    結果如下:

    7839,null,PRESIDENT 7844,7698,SALESMAN 7876,7788,CLERK 7900,7698,CLERK 7902,7566,ANALYST 7934,7782,CLERK

    3.4.2.5、單雙引號區(qū)別

    在導入數(shù)據(jù)時,默認的字符引號是單引號,這樣sqoop在解析的時候就安裝字面量來解析,不會做轉移:例如:

    --query 'select empno,mgr,job from emp WHERE empno>7800 and $CONDITIONS' \

    如果使用了雙引號,那么Sqoop在解析的時候會做轉義的解析,這時候就必須要加轉義字符 \ 如下:

    --query "select empno,mgr,job from emp WHERE empno>7800 and \$CONDITIONS" \

    3.4.2.6、MySql缺主鍵問題

    1、如果mysql的表沒有主鍵,將會報錯:

    19/12/02 10:39:50 ERROR tool.ImportTool: Import failed: No primary key could be found for table u1. Please specify one with -- split-by or perform a sequential import with '-m 1'

    解決方案:

    通過 --split-by 來指定要分片的列

    代碼如下:

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --query 'select empno,mgr,job from emp WHERE empno>7800 and $CONDITIONS' \ --target-dir hdfs://master:9000/sqoopdata/emp \ --delete-target-dir \ --split-by empno \ -m 1

    3.4.3、導入到Hive中

    3.4.3.1、說明

    ? Sqoop的導入工具的主要功能是將數(shù)據(jù)上傳到HDFS中的文件中。如果您有一個與HDFS集群相關聯(lián)的Hive,Sqoop還可以通過生成和執(zhí)行CREATETABLE語句來定義Hive中的數(shù)據(jù),從而將數(shù)據(jù)導入到Hive中。將數(shù)據(jù)導入到Hive中就像在Sqoop命令行中添加–hive-import選項。

    ? 如果Hive表已經(jīng)存在,則可以指定--hive-overwrite選項,以指示必須替換單元中的現(xiàn)有表。在將數(shù)據(jù)導入HDFS或省略此步驟之后,Sqoop將生成一個Hive腳本,其中包含使用Hive的類型定義列的CREATE表操作,并生成LOAD Data INPATH語句將數(shù)據(jù)文件移動到Hive的倉庫目錄中。

    在導入Hive之前先要配置Hadoop的Classpath才可以,否則會報類找不到錯誤,在/etc/profile末尾添加如下配置:

    export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HIVE_HOME/lib/*#刷新配置 source /etc/profile

    3.4.3.2、參數(shù)說明

    具體的參數(shù)如下:

    ArgumentDescription
    --hive-home 覆蓋環(huán)境配置中的$HIVE_HOME,默認可以不配置
    –hive-import指定導入數(shù)據(jù)到Hive中
    --hive-overwrite覆蓋當前已有的數(shù)據(jù)
    --create-hive-table是否創(chuàng)建hive表,如果已經(jīng)存在,則會失敗
    --hive-table 設置要導入的Hive中的表名

    3.4.3.3、實際導入案例

    具體導入演示代碼如下:

    提示: 為了看到演示效果,可以先在Hive刪除emp表

    [root@master sqoop] bin/sqoop import --connect jdbc:mysql://node2:3306/qfdb \ --username root \ --password 123123 \ --table emp \ --hive-import \ --hive-overwrite \ --fields-terminated-by ',' \ -m 1

    在Hive中查看表:

    hive> show tables; #結果如下: OK emp

    可以在Hive中查看數(shù)據(jù)是否導入:

    select * from emp; #結果如下: 7369 SMITH CLERK 7902 1980-12-17 800.0 NULL 20 7499 ALLEN SALESMAN 7698 1981-02-20 1600.0 300.0 30 7521 WARD SALESMAN 7698 1981-02-22 1250.0 500.0 30 7566 JONES MANAGER 7839 1981-04-02 2975.0 NULL 20 7654 MARTIN SALESMAN 7698 1981-09-28 1250.0 1400.0 30 7698 BLAKE MANAGER 7839 1981-05-01 2850.0 NULL 30 7782 CLARK MANAGER 7839 1981-06-09 2450.0 NULL 10 7788 SCOTT ANALYST 7566 1987-04-19 3000.0 NULL 20 7839 KING PRESIDENT NULL 1981-11-17 5000.0 NULL 10 7844 TURNER SALESMAN 7698 1981-09-08 1500.0 0.0 30 7876 ADAMS CLERK 7788 1987-05-23 1100.0 NULL 20 7900 JAMES CLERK 7698 1981-12-03 950.0 NULL 30 7902 FORD ANALYST 7566 1981-12-03 3000.0 NULL 20 7934 MILLER CLERK 7782 1982-01-23 1300.0 NULL 10

    四、Sqoop導入實戰(zhàn)

    4.1、Sqoop-import

    案例1

    表沒有主鍵,需要指定map task的個數(shù)為1個才能執(zhí)行

    Sqoop導入原理:

    ? Sqoop默認是并行的從數(shù)據(jù)庫源導入數(shù)據(jù)。您可以使用-m或–num-mappers參數(shù)指定用于執(zhí)行導入的map任務(并行進程)的數(shù)量。每個參數(shù)都取一個整數(shù)值,該整數(shù)值對應于要使用的并行度。默認情況下,使用四個任務。一些數(shù)據(jù)庫可以通過將這個值增加到8或16來改善性能。

    ? 默認情況下,Sqoop將標識表中的主鍵id列用作拆分列。從數(shù)據(jù)庫中檢索分割列的高值和低值,map任務操作整個范圍的大小均勻的組件。譬如ID的范圍是0-800,那么Sqoop默認運行4個進程,通過執(zhí)行 SELECT MIN(id), MAX(id) FROM emp找出id的范圍,然后把4個任務的id設置范圍是(0-200),(200-400),(400-600),(600-800)

    但是當一個表沒有主鍵時,上面的切分就無法進行,sqoop導入時就會出錯,這時候可以通過-m把mapper的數(shù)量設為1,只有也Mapper在運行,這時候就不需要切分,也可以避免主鍵不存在時候報錯的問題.

    #錯誤信息 ERROR tool.ImportTool: Import failed: No primary key could be found for table emp. Please specify one with --split-by or perform a sequential import with '-m 1'.

    導入代碼:

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp -m 1

    4.2、DBMS-HDFS

    案例2

    表沒有主鍵,使用–split-by指定執(zhí)行split的字段

    問題同上,如果表沒有主鍵,那么還有個辦法就是手工指定要拆分的列,通過--split-by來指定

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp \ --split-by empno \ --delete-target-dir \ --target-dir hdfs://master:9000/sqoopdata/emp -- 出錯 Caused by: java.sql.SQLException: null, message from server: "Host 'master' is not allowed to connect to this MySQL server"

    解決方案:

    先連接mysql:

    [root@master sqoop]# mysql -uroot -p

    (執(zhí)行下面的語句 .:所有庫下的所有表 %:任何IP地址或主機都可以連接)

    mysql> GRANT ALL PRIVILEGES ON . TO 'root'@'%' IDENTIFIED BY 'mysql' WITH GRANT OPTION;FLUSH PRIVILEGES;grant all privileges on . to root@"localhost" identified by "mysql" with grant option;FLUSH PRIVILEGES;

    案例3:條件導入

    需要導入的數(shù)據(jù)不是全部的,而是帶條件導入

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --table emp \ --split-by empno \ --where 'empno > 7777' \ --target-dir hdfs://master:9000/sqoopdata/emp

    案例4:部分字段導入

    :要導入的數(shù)據(jù),不想包含全部字段,只需要部分字段

    [root@master sqoop] bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb \ --username root --password 123123 \ --split-by empno \ --query 'select empno,ename,job from emp where empno > 7777 and $CONDITIONS' \ --target-dir hdfs://master:9000/sqoopdata/7

    4.3、DBMS-Hive

    案例5:將數(shù)據(jù)導入到hive中

    [root@master sqoop]# bin/sqoop import --connect jdbc:mysql://localhost:3306/qfdb --username root --password 123123 --table emp --hive-import -m 1

    五、Sqoop導出

    在Sqoop中,使用export進行導出,指的是從HDFS中導出數(shù)據(jù)到Mysql中:

    1、構建mysql的表:

    CREATE TABLE `u2` (`id` int(11) DEFAULT NULL,`age` int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `u3` (`id` int(11) DEFAULT NULL,`name` varchar(20) default NULL,`age` int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2、HDFS導出到mysql

    [root@master sqoop]# sqoop export --connect jdbc:mysql://master:3306/qfdb \ --username root \ --password root \ --table u2 \ --driver com.mysql.jdbc.Driver \ --export-dir '/1906sqoop/u2/*' \ -m 1# 方法二: 先重新導入數(shù)據(jù): [root@master sqoop]# sqoop import --connect jdbc:mysql://master:3306/qfdb \ --username root \ --password root \ --query 'select id,name,age from stu where id > 6 and $CONDITIONS' \ --driver com.mysql.jdbc.Driver \ --delete-target-dir \ --target-dir '/1906sqoop/u7' \ --split-by id \ -m 1 \ --fields-terminated-by '\t' \ --null-string '\\N' \ --null-non-string '0'導出語句: [root@master sqoop]# sqoop export --connect jdbc:mysql://hadoop01:3306/qfdb \ --username root \ --password root \ --table u3 \ --driver com.mysql.jdbc.Driver \ --export-dir '/1906sqoop/u7/*' \ --input-fields-terminated-by '\t' \ --input-null-string '\\N' \ --input-null-non-string '\\N' \ -m 1

    要注意以下問題

    • mysql表的編碼格式做為utf8,hdfs文件中的列數(shù)類型和mysql表中的字段數(shù)一樣
    • 導出暫不能由hbase表導出mysql關系型數(shù)據(jù)庫中
    • --export-dir是一個hdfs中的目錄,它不識別_SUCCESS文件
    • –query導入的時候注意設置問題。
    • 導出數(shù)據(jù)中有些列值有"null",會報沒法解析
    • 導出數(shù)據(jù)的類型需要和mysql中的一致(能自動轉沒有問題)

    六、Sqoop的Job

    6.1、增量導入數(shù)據(jù)

    6.1.1、使用場景

  • 經(jīng)常被操作不斷產(chǎn)生數(shù)據(jù)的表,建議增量。
  • 當某表基數(shù)很大,但是變化很小,也建議增量
  • 6.1.2、使用方式

    • query where : 能精確鎖定數(shù)據(jù)范圍
    • –incremental : 增量,最后記錄值來做的

    6.1.2.1、query where方式

    通過查詢具體日期的方式進行導入

    新建一個腳本文件

    [root@hadoop01 sqoop-1.4.7] vim ./import.sh

    寫入以下內(nèi)容:

    #!/bin/bash # yesterday=`date -d "1 days ago" "+%Y-%m-%d"` yesterday='2022-02-01' sqoop import --connect jdbc:mysql://master:3306/sales_source \ --username root \ --password 123123 \ --query "select * from sales_order where DATE(order_date) = '${yesterday}' and \$CONDITIONS" \ --driver com.mysql.jdbc.Driver \ --delete-target-dir \ --target-dir /user/hive/warehouse/sales_order/dt=${yesterday} \ --split-by id \ -m 1 \ --fields-terminated-by '\t' \ --null-string '\\N' \ --null-non-string '0'

    通過下面hdfs可以快速查詢到結果:

    [root@hadoop01 sqoop-1.4.7]# hdfs dfs -cat /user/hive/warehouse/sales_order/dt=2019-01-01/pa*

    6.1.2.2 increment的append方式:

    #將會手動維護last-value [root@hadoop01 sqoop-1.4.7]# sqoop import --connect jdbc:mysql://master:3306/sales_source \ --username root \ --password root \ --table sales_order \ --driver com.mysql.jdbc.Driver \ --target-dir /user/hive/warehouse/sales_order1/dt=2019-12-30 \ --split-by id \ -m 1 \ --check-column order_number \ --incremental append \ --last-value 80000 \ --fields-terminated-by '\t' \ --null-string '\\N' \ --null-non-string '0'

    使用下面命令查看:

    [root@hadoop01 sqoop-1.4.7]# hdfs dfs -cat /user/hive/warehouse/sales_order1/dt=2019-12-30/pa*

    6.2、Job操作

    job的好處:

  • 一次創(chuàng)建,后面不需要創(chuàng)建,可重復執(zhí)行job即可
  • 它可以幫我們記錄增量導入數(shù)據(jù)的最后記錄值
  • job的元數(shù)據(jù)默認存儲目錄:$HOME/.sqoop/
  • job的元數(shù)據(jù)也可以存儲于mysql中。
  • sqoop提供一系列的job語句來操作sqoop。

    $ sqoop job (generic-args) (job-args) [-- [subtool-name] (subtool-args)] $ sqoop-job (generic-args) (job-args) [-- [subtool-name] (subtool-args)]

    使用方法:

    usage: sqoop job [GENERIC-ARGS] [JOB-ARGS] [-- [<tool-name>] [TOOL-ARGS]]Job management arguments:--create <job-id> Create a new saved job--delete <job-id> Delete a saved job--exec <job-id> Run a saved job--help Print usage instructions--list List saved jobs--meta-connect <jdbc-uri> Specify JDBC connect string for the metastore--show <job-id> Show the parameters for a saved job--verbose Print more information while working

    列出sqoop的job:

    [root@master sqoop] sqoop job --list

    創(chuàng)建一個sqoop的job:

    [root@master sqoop]# sqoop job --create job1 -- import --connect jdbc:mysql://master:3306/qfdb \ --username root \ --password root \ --table u2 \ --driver com.mysql.jdbc.Driver \ --delete-target-dir \ --target-dir '/sqoop/job/job1' \ --split-by id \ -m 1

    執(zhí)行sqoop的job:

    #如報錯json包找不到,則需要手動添加 sqoop job --exec job1執(zhí)行的時候回讓輸入密碼: 輸入該節(jié)點用戶的對應的密碼即可 # 1、配置客戶端記住密碼(sqoop-site.xml)追加 <property><name>sqoop.metastore.client.record.password</name><value>true</value> </property># 2、將密碼配置到hdfs的某個文件,我們指向該密碼文件 說明:在創(chuàng)建Job時,使用--password-file參數(shù),而且非--passoword。主要原因是在執(zhí)行Job時使用--password參數(shù)將有警告,并且需要輸入密碼才能執(zhí)行Job。當我們采用--password-file參數(shù)時,執(zhí)行Job無需輸入數(shù)據(jù)庫密碼。 [root@master sqoop]# echo -n "root" > sqoop.pwd [root@master sqoop]# hdfs dfs -rm sqoop.pwd /input/sqoop.pwd [root@master sqoop]# hdfs dfs -put sqoop.pwd /input [root@master sqoop]# hdfs dfs -chmod 400 /input/sqoop.pwd [root@master sqoop]# hdfs dfs -ls /input -r-------- 1 hadoop supergroup 6 2018-01-15 18:38 /input/sqoop.pwd

    查看sqoop的job:

    [root@master sqoop] sqoop job --show sq1

    刪除sqoop的job:

    [root@master sqoop] sqoop job --delete sq1

    問題:

    1、創(chuàng)建job報錯:19/12/02 23:29:17 ERROR sqoop.Sqoop: Got exception running Sqoop: java.lang.NullPointerException java.lang.NullPointerExceptionat org.json.JSONObject.<init>(JSONObject.java:144)解決辦法: 添加java-json.jar包到sqoop的lib目錄中。 如果上述辦法沒有辦法解決,請注意hcatlog的版本是否過高,過高將其hcatlog包剔除sqoop的lib目錄即可。2、報錯:Caused by: java.lang.ClassNotFoundException: org.json.JSONObject 解決辦法: 添加java-json.jar包到sqoop的lib目錄中。

    6.3、metastore服務

    metastore服務是元數(shù)據(jù)服務,用于存儲sqoop的job相關信息,將信息保存于關系型數(shù)據(jù)庫中。

    優(yōu)點:

  • job信息更加有保障
  • 多個client之間共享job信息。
  • (1)在MySQL中創(chuàng)建Sqoop的元數(shù)據(jù)存儲數(shù)據(jù)庫 (如果有root可以用root)

    create database sqoop; create user 'sqoop'@'%' identified by 'sqoop'; grant all privileges on sqoop.* to 'sqoop'@'%'; flush privileges;

    (2)配置Sqoop的元數(shù)據(jù)存儲參數(shù)

    ? 在$SQOOP_HOME/conf/sqoop-site.xml中添加以下的參數(shù),在/code/sqoop-site.xml也可以查閱。

    sqoop.metastore.server.location:指定元數(shù)據(jù)服務器位置,初始化建表時需要。 sqoop.metastore.client.autoconnect.url:客戶端自動連接的數(shù)據(jù)庫的URL。 sqoop.metastore.client.autoconnect.username:連接數(shù)據(jù)庫的用戶名。 sqoop.metastore.client.enable.autoconnect:啟用客戶端自動連接數(shù)據(jù)庫。 sqoop.metastore.client.record.password:在數(shù)據(jù)庫中保存密碼,不需要密碼即可執(zhí)行sqoop job腳本。 sqoop.metastore.client.autoconnect.password:連接數(shù)據(jù)庫的密碼。<property><name>sqoop.metastore.client.enable.autoconnect</name><value>false</value><description>If true, Sqoop will connect to a local metastorefor job management when no other metastore arguments areprovided.</description></property><property><name>sqoop.metastore.client.autoconnect.url</name><value>jdbc:mysql://192.168.10.103:3306/sqoop</value></property><property><name>sqoop.metastore.client.autoconnect.username</name><value>root</value></property><property><name>sqoop.metastore.client.autoconnect.password</name><value>123456</value></property><property><name>sqoop.metastore.client.record.password</name><value>true</value></property><property><name>sqoop.metastore.server.location</name><value>/usr/local/sqoop/sqoop-metastore/shared.db</value></property><property><name>sqoop.metastore.server.port</name><value>16000</value></property>

    (3)重啟Sqoop服務

    ? 保存配置并重啟完成后,MySQL的sqoop庫中有了一個名為SQOOP_ROOT的空表。

    #啟動: [root@master sqoop]# sqoop metastore &#查看進程: [root@master sqoop]# jps sqoop#關閉: [root@master sqoop]# sqoop metastore --shutdown

    (4)預裝載SQOOP表

    insert into SQOOP_ROOT values (NULL, 'sqoop.hsqldb.job.storage.version', '0');

    (5)job相關操作

    [root@master sqoop]# sqoop job --list ###需要加--meta-connect創(chuàng)建job: [root@master sqoop]# sqoop job --create sq3 --meta-connect 'jdbc:mysql://master:3306/sqoop?user=root&password=root' -- import --connect jdbc:mysql://hadoop01:3306/test \ --username root \ --password root \ --table user_info \ --driver com.mysql.jdbc.Driver \ --delete-target-dir \ --target-dir '/1906sqoop/u9' \ --split-by id \ -m 1列出job: [root@master sqoop]# sqoop job --meta-connect 'jdbc:mysql://master:3306/sqoop?user=root&password=root' --list執(zhí)行job: [root@master sqoop]# sqoop job --meta-connect 'jdbc:mysql://master:3306/sqoop?user=root&password=root' --exec sq3執(zhí)行job并打印詳細信息: [root@master sqoop]# sqoop job --meta-connect 'jdbc:mysql://master:3306/sqoop?user=root&password=root' --exec sq3 -verbose

    ? 此時并不會返回先前已經(jīng)創(chuàng)建的myjob_incremental_import作業(yè),因為此時MySQL中沒有元數(shù)據(jù)信息。該命令執(zhí)行完成后,MySQL的sqoop庫中有了一個名為SQOOP_SESSIONS的空表,該表存儲sqoop job相關信息。

    (6)將表的存儲引擎修改為MYISAM(如job信息存儲到mysql的SQOOP_SESSIONS則不用執(zhí)行如下)

    alter table SQOOP_ROOT engine=myisam; alter table SQOOP_SESSIONS engine=myisam;

    因為每次執(zhí)行增量抽取后都會更新last_value值,如果使用Innodb可能引起事務鎖超時錯誤。

    七、Sqoop優(yōu)化

    7.1、-m與split-by的優(yōu)化

  • 小量數(shù)據(jù)時(200M左右) :最好使用一一個map,快且減少小文件。
  • 大量數(shù)據(jù)時:要特別考慮數(shù)據(jù)的特征,對于split- by最完美的情況是有一個:均勻分布的數(shù)字(如自增列)或時間字段,且這個字段還有索引(最好字段是int、tinyin),這樣在抽取時使得并發(fā)的每個sq1處理相近的數(shù)據(jù)量,并且sqoop附加的where條件可以使用索引。
  • split-by id,-m 2, 數(shù)據(jù)量1-100。第 一個mapper:(0,50]第二個mapper: (50, 100],對于m要綜合考慮數(shù)據(jù)量、I0、源數(shù)據(jù)庫的性能、集群的資源等等。一種簡單的考慮是最大不超過yarn.上分配給這個用戶的vcore個數(shù),最小“數(shù)據(jù)量/m”要夠一個128MB的文件。如果條件允許可以先設置一個值跑著試試,然后觀察源數(shù)據(jù)庫負載、集群I0以及運行時長等,再進行相應調整。
  • 7.2、 --fetch-size n

    一次取mysq1中批量讀取的數(shù)據(jù)條數(shù)。建議優(yōu)化如下:

  • 考慮一條數(shù)據(jù)的量。(如果2個字段和200個字段的–fetch-size不能一-樣)
  • 考慮數(shù)據(jù)庫的性能
  • 考慮網(wǎng)絡速度
  • 最好的狀態(tài)是一 次–fetch-si ze能滿足-一個mapper
  • 總結

    以上是生活随笔為你收集整理的Hadoop和关系型数据库间的数据传输工具——Sqoop的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。