使用Sqoop從MySQL導入數據到Hive和HBase 及近期感悟
Sqoop
大數據
Hive
HBase
ETL
基礎環境
sqoop:sqoop-1.4.5+cdh5.3.6+78,hive:hive-0.13.1+cdh5.3.6+397,hbase:hbase-0.98.6+cdh5.3.6+115
Sqool和Hive、HBase簡介
Sqoop
Sqoop是一個用來將Hadoop和關系型數據庫中的數據相互轉移的開源工具,可以將一個關系型數據庫(例如 : MySQL ,Oracle ,Postgres等)中的數據導進到Hadoop的HDFS中,也可以將HDFS的數據導進到關系型數據庫中。
Hive
不想用程序語言開發MapReduce的朋友比如DB們,熟悉SQL的朋友可以使用Hive開離線的進行數據處理與分析工作。
Hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供簡單的sql查詢功能,可以將sql語句轉換為MapReduce任務進行運行。
注意Hive現在適合在離線下進行數據的操作,就是說不適合在掛在真實的生產環境中進行實時的在線查詢或操作,因為一個字“慢”。
Hive起源於FaceBook,在Hadoop中扮演數據倉庫的角色。建立在Hadoop集群的最頂層,對存儲在Hadoop群上的數據提供類SQL的接口進行操作。你可以用 HiveQL進行select、join,等等操作。
如果你有數據倉庫的需求並且你擅長寫SQL並且不想寫MapReduce jobs就可以用Hive代替。
Hive的內置數據類型可以分為兩大類:(1)、基礎數據類型;(2)、復雜數據類型。其中,基礎數據類型包括:TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY、TIMESTAMP、DECIMAL、CHAR、VARCHAR、DATE。
下面的表格列出這些基礎類型所占的字節以及從什么版本開始支持這些類型。
數據類型 | 所占字節 | 開始支持版本 |
---|---|---|
TINYINT | 1byte: -128 ~ 127 | |
SMALLINT | 2byte:-32,768 ~ 32,767 | |
INT | 4byte:-2,147,483,648 ~ 2,147,483,647 | |
BIGINT | 8byte:-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | |
BOOLEAN | ||
FLOAT | 4byte單精度 | |
DOUBLE | 8byte雙精度 | |
STRING | ||
BINARY | 從Hive0.8.0開始支持 | |
TIMESTAMP | 從Hive0.8.0開始支持 | |
DECIMAL | 從Hive0.11.0開始支持 | |
CHAR | 從Hive0.13.0開始支持 | |
VARCHAR | 從Hive0.12.0開始支持 | |
DATE | 從Hive0.12.0開始支持 |
復雜類型包括ARRAY、MAP、STRUCT、UNION,這些復雜類型是由基礎類型組成的。
HBase
HBase作為面向列的數據庫運行在HDFS之上,HDFS缺乏隨即讀寫操作,HBase正是為此而出現。HBase以Google BigTable為藍本,以鍵值對的形式存儲。項目的目標就是快速在主機內數十億行數據中定位所需的數據並訪問它。
HBase是一個數據庫,一個NoSql的數據庫,像其他數據庫一樣提供隨即讀寫功能,Hadoop不能滿足實時需要,HBase正可以滿足。如果你需要實時訪問一些數據,就把它存入HBase。
你可以用Hive作為靜態數據倉庫,HBase作為數據存儲,放那些進行一些會改變的數據。在Hive中,普通表是存儲在HDFS中,而你可以通過創建EXTERNAL TABLE外表來指定數據存儲位置,可以是系統目錄,也可以是ElasticSearch,還可以是HBase。
在使用Sqoop從Mysql導出數據入Hadoop時,就需要考慮是直接入Hive(此時是普通表),還是導入數據到HBase,Sqoop同時支持導入這兩種導入。
測試Sqoop
#測試MySQL連接
[hdfs@node196 bin]$ sqoop list-databases --connect jdbc:mysql://192.168.180.11/angel --username anqi –P
#檢驗SQL語句
[hdfs@node196 bin]$ sqoop eval --connect jdbc:mysql://192.168.180.11/angel --username anqi --password anqi_mima \
--query "SELECT xi.*, jing.name,wang.latitude,wang.longitude \
FROM xi ,jing, wang \
WHERE xi.id=jing.foreignId AND wang.id=xi.id AND xi.date>='2015-09-01' AND xi.date<='2015-10-01'"
以上Sqoop語句執行過后,可以確認Sqoop運行正常,Sqoop連接MySQL正常。
使用Sqoop從MySQL導入數據到Hive
使用復雜SQL
#從MySQL導入數據到Hive
[hdfs@node196 bin]$ sqoop eval --connect jdbc:mysql://192.168.180.11/angel --username anqi --password anqi_mima \
--query "SELECT xi.*, jing.name,wang.latitude,wang.longitude \
FROM xi ,jing, wang \
WHERE xi.id=jing.foreignId AND wang.id=xi.id AND xi.date>='2015-09-01' AND xi.date<='2015-10-01' \
AND \$CONDITIONS" \
--split-by date --hive-import -m 5 \
--target-dir /user/hive/warehouse/anqi_wang \
--hive-table anqi_wang
注意:
由於使用Sqoop從MySQL導入數據到Hive需要指定target-dir,因此導入的是普通表而不能為外部表。
以下簡要列舉了Sqoop的執行過程:
BoundingValsQuery: SELECT MIN(date), MAX(date) FROM (SELECT xi.*, jing.name,wang.latitude,wang.longitude FROM xi ,jing, wang WHERE xi.id=jing.foreignId AND wang.id=xi.id AND xi.date>='2015-09-01' AND xi.date<='2015-10-01' AND (1 = 1) ) AS t1
15/10/13 13:11:47 INFO mapreduce.JobSubmitter: number of splits:5
15/10/12 13:40:28 INFO mapreduce.Job: map 0% reduce 0%
15/10/12 13:40:39 INFO mapreduce.Job: map 20% reduce 0%
15/10/12 13:40:40 INFO mapreduce.Job: map 40% reduce 0%
15/10/12 13:40:47 INFO mapreduce.Job: map 60% reduce 0%
15/10/12 13:40:48 INFO mapreduce.Job: map 80% reduce 0%
15/10/12 13:40:52 INFO mapreduce.Job: map 100% reduce 0%
可以看出,--split-by設置后,job按設置值切分,切分個數為-m設置值(-m 5 不設置的話默認job切分數是4)。經檢驗,此種較復雜的SQL語句,Sqoop支持得很好。
調整Hive數據類型
上面任務執行成功后,經過檢測,發現Hive表結構中的數據類型與MySQL對應列有如下關系:
MySQL(bigint) --> Hive(bigint)
MySQL(tinyint) --> Hive(tinyint)
MySQL(int) --> Hive(int)
MySQL(double) --> Hive(double)
MySQL(bit) --> Hive(boolean)
MySQL(varchar) --> Hive(string)
MySQL(decimal) --> Hive(double)
MySQL(date/timestamp) --> Hive(string)
可以看出MySQL的decimal類型變成了Hive中的double類型。此時需要在導入時通過--map-column-hive 作出映射關系指定,如下所示:
[hdfs@node196 bin]$ sqoop import \
--connect jdbc:mysql://192.168.184.12/angel --username anqi --password anqi_mima \
--query "SELECT * FROM xi WHERE date>='2015-09-16' AND date<='2015-10-01' \
AND \$CONDITIONS" \
--split-by date --hive-import -m 5 \
--map-column-hive cost="DECIMAL",date="DATE" \
--target-dir /user/hive/warehouse/xi \
--hive-table xi
以上命令可以執行成功,然而Hive列類型設置為DECIMAL時,從Mysql[decimal(12,2)]-->Hive[decimal]會導致導入后小數丟失。
注意:
對於cost="DECIMAL(10,2)"這樣指定精確度的映射語句的執行,在Sqoop1.4.5中執行失敗。這是Sqoop1.4.5的一個BUG,詳情見:https://issues.apache.org/jira/browse/SQOOP-2103,它在1.4.7版本中修復。
不斷更新
將上面Sqoop語句執行兩次,在執行第二次時會出現錯誤:
ERROR tool.ImportTool: Encountered IOException running import job: org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://node190:8020/user/hive/warehouse/anqi_wang already exists
這表示HDFS中已經存在相應存儲,此時需要執行Sqoop-Hive的增量導入語句。
注意:
由於Hive沒有rowkey,其hdfs存儲決定了Sqoop-Hive只能添加,update更新導入無法進行。
使用Sqoop從MySQL導入數據到HBase
使用復雜SQL
#從MySQL導入數據到HBase
[hdfs@node196 bin]$ sqoop import \
--connect jdbc:mysql://192.168.184.12/angel --username anqi --password anqi_mima \
--query "SELECT * FROM xi WHERE 1=1 \
AND \$CONDITIONS" \
--hbase-table hxi --hbase-create-table \
--hbase-row-key id --split-by date -m 7 \
--column-family aitanjupt
上面SQL語句較簡單。經檢驗,更復雜的SQL語句,Sqoop支持得很好,導入正常。
不斷更新
以上指定了HBase的Rowkey后,再次執行從MySQL導入數據到HBase的Sqoop語句,基於相同的Rowkey值,HBase內相應的行會進行更新替換。
Hive使用HBase數據
CREATE EXTERNAL TABLE default.angel(
id BIGINT,
username STRING,
password STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key, angel:username, angel:password")
TBLPROPERTIES("hbase.table.name" = "hxi");
關於Hive使用存儲在HBase中的數據,更多詳細信息可以查看《使用Hive或Impala執行SQL語句,對存儲在HBase中的數據操作》一文。
關於Sqoop2
架構上,Sqoop1使用MapOnly作業進行Hadoop(HDFS/HBase/Hive)同關系數據庫進行數據的導入導出,用戶使用命令行方式與之交互,數據傳輸和數據格式緊密耦合;易用性欠佳,Connector數據格式支持有限,安全性不好,對Connector的限制過死。Sqoop2則建立了集中化的服務,負責管理完整的MapReduce作業,提供多種用戶交互方式(CLI/WebUI/RESTAPI),具有權限管理機制,具有規范化的Connector,使得它更加易用,更加安全,更加專注。
綜上所述
使用Sqoop從MySQL導入數據到HBase要比導入到Hive方便,使用Hive對HBase數據操作時,也無decimal精度相關BUG,並且可以很好的支持更新。因此建議使用Sqoop從MySQL導入數據到HBase,而非直接Hive。
經過測試,使用Sqoop從MySQL導入數據到HBase,100萬條需花費7~12分鍾。impala對於hbase的查詢效率也沒有對hdfs效率高。
本文會不定期更新,若有不對之處請前往原文出處:http://www.cnblogs.com/wgp13x/ 進行指正。
其他感受
在大數據領域浸染的多了,才知道當前社會上的公司對於大數據方向的技術都是什么樣的理解。有的公司數據量足夠大,但數據並無價值或者價值不夠大,我們稱之為LU(large but unavailable)類型公司;有的公司數據量不多,但都價值連城,我們稱之為SV(small but valuable)類型公司;有的公司數據量很大,數據也都很有價值,我們稱之為LV(large and valuable)類型公司。
LU公司市場上有很多,造成數據無價值的因素可能是有數據本身的原因,也有產品的原因,他們也經常想要在當前環境下試下大數據的水,這便要細心甄別。SV公司也有不少,對於他們而言,好的數據分析師比大數據平台更重要,欲要試水大數據,還是要對數據量有清晰的預估。LV公司是最需要搭建大數據平台的,但又往往他們沒有技術與欲望去做這件事,這也比較可恨。
簡而言之,想做的不一定需要,不做的不一定不需要。