SQL處理二維表格資料,是一種最樸素的工具,NoSQL是Not Only SQL,即不僅僅是SQL。從MySQL匯入資料到HDFS檔案系統中,最簡單的一種方式就是使用Sqoop,然後將HDFS中的資料和Hive建立對映。通過Sqoop作為資料橋樑,將傳統的資料也存入到NoSQL中來了,有了資料,猴戲才剛剛開始。
01 猴年伊始
SQL處理二維表格資料,是一種最樸素的工具,查詢、更新、修改、刪除這四種對資料的基本操作,是處理資料的一個巨大進步。近些年,各種新的資料處理技術興起了,都想革SQL的命,這些技術也被大家統稱為NoSQL。
NoSQL最初的意思是No SQL,估計應該是想和SQL劃清界線,就像GNU的遞迴縮寫GNU is Not Unix一樣。後來發現,雖然大量的NoSQL技術起來了,但SQL還是活得好好的,照樣發揮著很多不可替代的作用。漸漸地,大家也發現,原來這些新技術,也只是在不同的應用場景下對SQL的補充,因此也慢慢為NoSQL正名了,原來是Not Only SQL,即不僅僅是SQL,還有很多其它的處理非結構化資料和應用於各種場景的技術。甚至很多技術,雖然是在NoSQL的框架下,但也慢慢的又往SQL方向發展。
NoSQL是一種技術或者框架的統稱,包括以Mongodb,Hadoop,Hive,Cassandra,Hbase,Redis等為代表的框架技術,這些都在特定的領域有很多實際的應用。而SQL領域的開源代表自然是MySQL了。
很多企業中,業務資料都是存放在MySQL資料庫中的,當資料量太大後,單機版本的MySQL很難滿足業務分析的各種需求。此時,可能就需要將資料存入Hadoop叢集環境中,那麼本文的主角Sqoop便適時的出現了,用來架起SQL與NoSQL之間的資料橋樑。
02 MySQL匯入HDFS
從MySQL匯入到HDFS檔案系統中,是最簡單的一種方式了,相當於直接將表的內容,匯出成檔案,存放到HDFS中,以便後用。
Sqoop最簡單的使用方式,就是一條命令,唯一需要的是配置相應的引數。sqoop可以將所有引數寫在一行上,也可以寫在配置檔案裡面。因為匯入的選項過多,通常我們都把引數寫在配置檔案裡面,以便更好的除錯。在匯入到HDFS的過程中,需要配置以下引數:
- 使用import指令
- 資料來源配置:驅動程式,IP地址,庫,表,使用者名稱,密碼
- 匯入路徑,以及是否刪除存在的路徑
- 並行程式數,以及使用哪個欄位進行切分
- 欄位選擇,以及欄位分隔符
- 查詢語句:自定義查詢,Limit可以在此處使用
- 查詢條件:自定義條件
配置檔案示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# 檔名:your_table.options import --connect jdbc:mysql://1.2.3.4/db_name --username your_username --password your_passwd --table your_table --null-string NULL --columns id, name # --query # select id, name, concat(id,name) from your_table where $CONDITIONS limit 100 # --where # "status != 'D'" --delete-target-dir --target-dir /pingjia/open_model_detail --fields-terminated-by '01' --split-by id --num-mappers 1 |
示例引數說明:
- import指令,說明是匯入,這兒的“入”是相對於hdfs來說的,即從MySQL匯入到hdfs檔案系統中。
- 以雙橫線開頭的是引數,其中connect配置資料庫驅動及來源,此處配置了mysql及ip地址和資料庫名。
- username, password配置使用者名稱密碼。table配置來源表名,此處需要注意,如果後面使用了query的方式,即指定了查詢語句,此處table需要註釋。
- columns配置了從表中讀取的欄位,可以是全部,也可以是部分。同上所求,如果指定了query則不需要配置columns
- query是自己指定匯出的sql語句,如果需要自定義匯出,則使用。注意,這兒有一個where條件,無論是否使用條件,都需要帶上
where $CONDITIONS,$CONDITIONS
是後面配置的條件。 - where用於單獨設定查詢條件
- target-dir用於指定匯入的目錄,從mysql中匯入到hdfs中的資料是直接匯入到目錄,而不是直接指定檔案,檔名會自動生成。另外,如果需要在hive中使用分割槽,此處應該用子分割槽的名字。比如,增加一個year=2015的分割槽,那麼,建立目錄的時候,把資料存入子目錄year=2015中去,這樣後面在hive中直接增加分割槽對映即可。delete-target-dir是如果目錄存在便刪除,否則會報錯。
- fields-terminated-by用於配置匯出的各欄位之間,使用的分隔符,為防止資料內容裡面包括空格,通常不推薦用空格,’01’也是Hive中推薦的欄位分隔符,當然,我們也是為了更好的在Hive中使用資料才這樣設定。
- num-mappers是指定並行的mapper(程式數),這也是使用sqoop的一大優勢,並行可以加快速度,預設使用4個程式並行。同時,split-by需要設定為一個欄位名,通常是id主鍵,即在這個欄位上進行切分成4個部分,每個程式匯入一部分。另外,配置幾個程式數,最後目錄中生成的檔案便是幾個,因此對於小表,建立設定num-mappers為1,最後只生成一個檔案。
上面使用了配置檔案的方式,在配置檔案中,可以使用#註釋,也可以使用空行,這樣方便做除錯。配置好上面的引數檔案,即可呼叫測試:
1 |
sqoop --options-file your_table.options |
如果不報錯,最後會顯示匯入的檔案大小與檔案行數。
這是一個匯入速度的記錄,供參考:
Transferred 3.9978 GB in 811.4697 seconds (5.0448 MB/sec)
Retrieved 18589739 records.Transferred 3.4982 GB in 350.2751 seconds (10.2266 MB/sec)
Retrieved 16809945 records.Transferred 846.5802 MB in 164.0938 seconds (5.1591 MB/sec)
Retrieved 5242290 records.Transferred 172.9216 MB in 72.2055 seconds (2.3949 MB/sec)
Retrieved 1069275 records.
03 增量匯入
HDFS檔案系統是不允許對記錄進行修改的,只能對檔案進行刪除,或者追加新檔案到目錄中。但Mysql資料中的增、刪、改是最基本的操作,因此匯入的資料,可能一會兒就過期了。
從這兒也可以看出,並非所有資料都適合匯入到HDFS,通常是日誌資料或者非常大的需要統計分析的資料。通常不太大的表,也建議直接完整匯入,因為本身匯入速度已經夠快了,千萬級別的資料,也只是幾分鐘而已。
如果不考慮資料的修改問題,只考慮資料的增加問題,可以使用append模式匯入。如果需要考慮資料修改,則使用lastmodified的模式。
增量的方式,需要指定以下幾個引數:
1 2 3 4 5 6 |
--check-column filed_name --incremental append|lastmodified --last-value value |
- check_colume:配置檢查增量的欄位,通常是id欄位,或者時間欄位
- incremental: 增量的方式,追加或者最後修改,追加從上一次id開始,只追加大於這個id的資料,通常用於日誌資料,或者資料不常更新的資料。最後修改,需要本身在Mysql裡面,資料每次更新,都更新維護一個時間欄位。在此,表示從指定的時間開始,大於這個時間的資料都是更新過的,都要匯入
- last-value: 指定了上一次的id值或者上一次的時間
04 對映到hive
匯入到HDFS中的資料,要進行統計分析,甚至會需要對多個文件進行關聯分析,還是有不便之處,此時可以再使用Hive來進行資料關聯。
首先,需要在Hive中建立表結構,只選擇性的建立匯入的資料欄位,比如匯入了id和name兩個欄位,則Hive表也只建立這兩個欄位。
另外,最好通過external關鍵字指定建立外部表,這樣Hive只管理表的後設資料,真實的資料還是由HDFS來儲存和手工進行更新。即使刪除了Hive中的表,資料依然會存在於HDFS中,還可以另做它用。
建表,要指定欄位的資料格式,通常只需要用四資料來替換Mysql的資料:
string ==> 替換char,varchar
int ==> 替換int
float ==> 替換float
timestamp ==> 替換datetime
另外,還需要指定儲存格式,字元分隔符和分割槽等,常用的一個建表語句如:
1 2 3 4 5 6 7 8 |
CREATE external TABLE your_table ( id int, name string ) PARTITIONED BY (pdyear string) ROW FORMAT DELIMITED fields terminated by '01' STORED AS TEXTFILE LOCATION '/path/your_table'; |
上面指定了一個分割槽pdyear,欄位分隔符為’01’,儲存成TEXTFILE格式,資料檔案的目錄為/path/your_table(從MySQL匯入到HDFS的目錄)。
如果匯入的資料,配置了分割槽,即如下目錄結構:
/path/your_table/pdyear=2015
/path/your_table/pdyear=2016
則建立表後,表裡面沒有對應上資料,需要新增分割槽到hive表中,在hive中執行以下語句:
1 2 |
alter table your_table add partition (pdyear='2015') location '/path/your_table/pdyear=2015'; alter table your_table add partition (pdyear='2016') location '/path/your_table/pdyear=2016'; |
完成上面的操作後,即可以在Hive中進行查詢和測試,檢視是否有資料。Hive的hql語法,源於mysql的語法,只是對部分細節支援不一樣,因此可能需要除錯一下。
05 HDFS匯出到MySQL
在Hive中進行了一系列的複雜統計分析後,最後的結論可能還是需要儲存到Mysql中,那麼可以在Hive語句中,將分析結果匯出到HDFS中儲存起來,最後再使用Sqoop將HDFS的檔案匯入到MySQL表中,方便業務使用。
匯出的配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
export --connect jdbc:mysql://1.2.3.4/db_name --username your_username --password your_passwd --table your_table --input-null-string '\N' --update-mode allowinsert --update-key id --export-dir /path/your_table/ --columns id,name --input-fields-terminated-by '01' |
引數說明:
- export:指令說明是匯出
- update-mode:allowinsert,配置了,使用更新模式,即如果Mysql中已經有資料了,則進行更新,如果沒有,則插入。判斷的欄位使用update-key引數配置,需要這個欄位是唯一索引的欄位。
- input-null-string:Hive中,匯出的NULL為字元N,要還原到Mysql中,依然為MyQL的Null的話,需要使用這個配置,指定NULL的字串為’N’
另外,匯出的時候,如果Mysql表中有自動增長的主鍵欄位,可以留空,生成資料的時候會自動填充。
06 猴戲開始
將MySQL中的資料匯入到HDFS中,又將HDFS中的資料建立了到Hive表的對映。至此,通過Sqoop工具作為SQL與NoSQL的資料橋樑,將傳統的資料也存入到NoSQL中來了,有了資料,便是開始。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式