Hadoop-Hive簡介

一、前言

1.特別的計算模型:MapReduce

  • 其可以將任務分割成多個處理單元,然後分散到一羣家用或者服務器級別的硬件機器上,從而降低成本,並提供水平可伸縮性。
  • 這個計算模型下面組件被稱爲Hadoop分散式文件系統(HDFS)
  • 這個系統是可拔插的

2.Hive出現的原因

  • 用戶希望從現有的數據庫基礎框架轉移到Hadoop上
  • 而這個框架是基於傳統關係型數據庫和接口查詢語句(SQL)的,爲了解決這個問題,出現了Hive

3.Hive出現了查詢語句:

  • Hive查詢語句(HiveQL或HQL)
  • 查詢存儲在Hadoop中的數

4.SQL知識分佈廣泛的一個原因:

  • 它有效地、合理地、且直觀地組織和使用數據模型。

5.Hive應用:

  • Hive可以將大多數查詢轉換爲MapReduce任務(job),進而在介紹一個令人熟悉的SQL抽象的同時,拓展了Hadoop的可擴展性。
  • Hive最適合數據倉庫的應用程序,使用該應用程序進行相關的靜態分析,不需要快速響應給出結果,而且數據本身 頻繁變化。

6.Hive不是一個完整的數據庫:

  • Hive不支持記錄級別的更新、插入或刪除
  • 用戶可以通過查詢生成新表或者將查詢結果導入到文件中
  • Hive查詢延時比較嚴重

7.Hive不支持(OLTP)聯機事務處理

  • Hive不支持OLTP(聯機事務處理)所需要的關鍵功能,更接近於一個OLAP(聯機分析技術)工具。但是並沒有滿足OLAP中的”聯機“部分,至少目前沒有滿足。由於延時嚴重。

8.Hive最適合數據倉庫的應用程序

  • 可以維護海量數據,而且可以對數據進行挖掘,然後形成意見和報告

二、介紹

1.Hive是什麼?

1).MapReduce開發:

  • 開發調試麻煩,只能使用Java開發,需要對hadoop的底層及api比較瞭解才能開發出複雜的代碼

2).HQL:

  1. Hive是基於Hadoop的一個數據倉庫。
  2. 可以將結構化的數據文件映射成爲一張數據庫表,並提供完整的SQL查詢功能。
  3. 可以將SQL語句轉化爲MapReduce任務進行。
  4. 其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合數據倉庫的統計分析。
  5. Hive是建立在 Hadoop 上的數據倉庫基礎架構。它提供了一系列的工具,可以用來進行數據提取轉化加載(ETL),這是一種可以存儲、查詢和分析存儲在 Hadoop 中的大規模數據的機制。
  6. Hive 定義了簡單的類 SQL 查詢語言,稱爲 HiveQL,它允許熟悉 SQL 的用戶查詢數據。
  7. 同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper 和 reducer 來處理內建的 mapper 和 reducer 無法完成的複雜的分析工作。
  8. Hive不支持在線事務處理,也不支持行級的插入和更新和刪除。

3).數據倉庫簡介

  • 數據倉庫,是爲企業所有級別的決策制定過程,提供所有類型數據支持的戰略集合。
  • 它是單個數據存儲,出於分析性報告和決策支持目的而創建。
  • 需要業務智能的企業,提供指導業務流程改進、監視時間、成本、質量以及控制。

2.Hive的安裝配置

  1. 首先需要hadoop的支持,啓動好hadoop

  2. 下載:從apache官網下載新版本hive,要注意和hadoop版本的匹配。

  3. 支持:
    需要對應版本jdk的支持
    需要安裝並運行hadoop

  4. 安裝:
    將下載好的hive安裝包上傳到linux中。
    解壓:tar -zxvf apache-hive-1.2.0-bin.tar.gz

  5. 啓動:
    進入hive/bin目錄,直接運行hive命令,即可進入hive提示符。
    hive不需要任何配置就可以運行,因爲它可以通過HADOOP_HOME環境變量獲知hadoop的配置信息。


  6. 在使用hadoop2.5.x環境下,啓動hive發現報錯:java.lang.IncompatibleClassChangeError: Found class jline.Terminal, but interface was expected


    造成這個錯誤的原因是因爲jline.Terminal這個類有錯誤。


    複製hive/lib/jline-2.12.jar替換hadoop/share/hadoop/yarn/lib中的jline-0.9.x.jar,重啓hadoop和hive即可。

    直接將hadoop升級到更高版本,如2.7.x中已經解決此問題。


3.HIVE入門

$show databases;

執行後發現默認有一個庫default

$show tables;

發現沒有任何表,證明不use其他庫時,默認就是default庫。

$create database tedu;

發現在hdfs中多出了/user/hive/warehouse/tedu.db目錄
結論1: hive中的數據庫對應hdfs中/user/hive/warehouse目錄下以.db結尾的目錄。

$use tedu;
$create table student (id int,name string);
$show tables;
$desc student;
$show create table student;

發現正確創建出來了表。
發現在hdfs中多出了/user/hive/warehouse/tedu.db/sutdent目錄
結論2: hive中的表對應hdfs/user/hive/warehouse/[db目錄]中的一個目錄

$load data local inpath '../mydata/student.txt' into table student;

發現/user/hive/warehouse/tedu.db/sutdent下多出了文件

$select * from student;

發現查出的數據不正確,原因是建表時沒有指定分隔符。默認的分隔符是空格。

$create table student2 (id int,name string) row format delimited fields terminated by '\t';
$load data local inpath '../mydata/student.txt' into table student2;
$select * from student2;

發現正確查詢出了數據。
結論3: hive中的數據對應當前hive表對應的hdfs目錄中的文件。

$select count(*) from student;

發現執行了mapreduce作業,最終現實了結果
結論4: hive會將命令轉換爲mapreduce執行。

$use default;
$create table teacher(id int,name string);

發現在hive對應的目錄下多出了 tedu.db 文件夾,其中包含user文件夾。
結論5: hive默認的default數據庫直接對應/user/hive/warehouse目錄,在default庫中創建的表直接會在該目錄下創建對應目錄。


4.HIVE配置mysql metastore

1). hive中除了保存真正的數據以外還要額外保存用來描述庫、表、數據的數據,稱爲hive的元數據。這些元數據又存放在何處呢?

  • 如果不修改配置hive默認使用內置的derby數據庫存儲元數據。
  • derby是apache開發的基於java的文件型數據庫。
  • 可以檢查之前執行命令的目錄,會發現其中產生了一個metastore.db的文件,這就是derby產生的用來保存元數據的數據庫文件。

2) derby數據庫

  • derby數據庫僅僅用來進行測試,真正使用時會有很多限制。
  • 最明顯的問題是不能支持併發。
  • 經測試可以發現,在同一目錄下使用無法同時開啓hive,不同目錄下可以同時開啓hive但是會各自產生metastore.db文件造成數據無法共同訪問。
  • 所以真正生產環境中我們是不會使用默認的derby數據庫保存hive的元數據的。

hive目前支持derby和mysql來存儲元數據。

3)配置hive使用mysql保存元數據信息:

刪除hdfs中的/user/hive

hadoop fs -rmr /user/hive   

複製hive/conf/hive-default.xml.template爲hive-site.xml

cp hive-default.xml.template hive-site.xml 

<configuration> 中進行配置

<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop01:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>

<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>

<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>

<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>

!!手動創建hive元數據庫,注意此庫必須是latin1,否則會出現奇怪問題!所以推薦手動創建!並且創建庫之前不能有任意的hive操作,否則自動創建出來的庫表將使用mysql默認的字符集,仍然報錯!
!!另一種方法是修改mysql的配置文件,讓mysql默認編碼集就是latin1,這樣hive自動創建的元數據庫就是latin1的了,但是這已修改將會影響整個mysql數據庫,如果mysql中有其他庫,這種方式並不好。

create database hive character set latin1;

將mysql的連接jar包拷貝到$HIVE_HOME/lib目錄下

如果出現沒有權限的問題,在mysql授權(在安裝mysql的機器上執行)

mysql -uroot -p #(執行下面的語句  *.*:所有庫下的所有表   %:任何IP地址或主機都可以連接)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;

再進入hive命令行,試着創建庫表發現沒有問題。
測試發現開啓多個連接沒有問題。
連接mysql,發現多了一個hive庫。其中保存有hive的元數據。DBS-數據庫的元數據信息,TBLS-表信息。COLUMNS_V2表中字段信息,SDS-表對應hdfs目錄


5.HIVE外部表 分區表

1)外部表

創建hive表,經過檢查發現TBLS表中,hive表的類型MANAGED_TABLE.
在真實開發中,很可能在hdfs中已經有了數據,希望通過hive直接使用這些數據作爲表內容。
此時可以直接創建出hdfs文件夾,其中放置數據,再在hive中創建表來管理,這種方式創建出來的表叫做外部表。

#創建目錄,上傳已有文件
hadoop fs -mkdir /data
hadoop fs -put student.txt /datax/a.txt  
hadoop fs -put student.txt /datax/b.txt  
#在hive中創建外部表管理已有數據
create external table ext_student(id int ,name string) row format delimited fields terminated by '\t' location '/datax';

經過檢查發現可以使用其中的數據。成功的建立了一張外部表。

#vim ppp.txt
        1   x
        2   y
        3   z
#hadoop fs - put  peo.avi

再在該目錄下手動創建文件,能不能查詢出來呢?
發現是可以的。

不管是內部表還是外部表,新增的文件都可以自動被應用。

在刪除表時,內部表一旦刪除對應元數據和hdfs中的文件夾和文件都會被刪除。外部表只刪除元數據,對應的hdfs中的文件夾和文件不會被刪除。

2)分區表

hive也支持分區表
對數據進行分區可以提高查詢時的效率
普通表和分區表區別:有大量數據增加的需要建分區表

create table book (id bigint, name string) partitioned by (category string) row format delimited fields terminated by '\t'; 

在創建分區表時,partitioned字段可以不在字段列表中。生成的文件自動就會具有該字段。



分區表加載數據

load data local inpath './book_china.txt' overwrite into table book partition (category='china');
load data local inpath './book_us.txt' overwrite into table book partition (pubdate='2015-01-11');
select * from book;
select * from book where pubdate='2010-08-22';

經檢查發現分區也是一個目錄。
此時手動創建目錄是無法被hive使用的,因爲元數據庫中沒有記錄該分區。
如果需要將自己創建的分區也能被識別,需要執行:

ALTER TABLE book add  PARTITION (category = 'zazhi') location '/user/hive/warehouse/datax.db/book/category=zazhi';

6.HIVE語法

0).數據類型

TINYINT - byte
SMALLINT - short
INT - int
BIGINT - long
BOOLEAN - boolean
FLOAT - float
DOUBLE - double
STRING - String
TIMESTAMP - TimeStamp
BINARY - byte[]

1).create table

  • CREATE TABLE 創建一個指定名字的表。如果相同名字的表已經存在,則拋出異常;用戶可以用 IF NOT EXIST
    選項來忽略這個異常。
  • EXTERNAL 關鍵字可以讓用戶創建一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION),Hive
    創建內部表時,會將數據移動到數據倉庫指向的路徑;若創建外部表,僅記錄數據所在的路徑,不對數據的位置做任何改變。在刪除表的時候,內部表的元數據和數據會被一起刪除,而外部表只刪除元數據,不刪除數據。
  • LIKE 允許用戶複製現有的表結構,但是不復制數據。
  • 有分區的表可以在創建的時候使用 PARTITIONED BY 語句。一個表可以擁有一個或者多個分區,每一個分區單獨存在一個目錄下。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[
 [ROW FORMAT row_format] [STORED AS file_format]
 | STORED BY 'storage.handler.class.name' [ WITH SERDEPROPERTIES (...) ]  (Note:  only available starting with 0.6.0)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)]  (Note:  only available starting with 0.6.0)
[AS select_statement]  (Note: this feature is only available starting with 0.5.0.)

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
  LIKE existing_table_name
  [LOCATION hdfs_path]

data_type
  : primitive_type
  | array_type
  | map_type
  | struct_type

primitive_type
  : TINYINT
  | SMALLINT
  | INT
  | BIGINT
  | BOOLEAN
  | FLOAT
  | DOUBLE
  | STRING

array_type
  : ARRAY < data_type >

map_type
  : MAP < primitive_type, data_type >

struct_type
  : STRUCT < col_name : data_type [COMMENT col_comment], ...>

row_format
  : DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

file_format:
  : SEQUENCEFILE
  | TEXTFILE
  | RCFILE     (Note:  only available starting with 0.6.0)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
  • 練習:
創建一張內部表
    create table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t';
創建一張外部表
    create external table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t';
創建一張帶有分區的外部表
    create external table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t' partitioned by 'ccc';

2).Alter Table

(1)Add Partitions

ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
partition_spec:
  : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)

練習:修改表增加分區

(2)Drop Partitions

ALTER TABLE table_name DROP partition_spec, partition_spec,...

(3)Rename Table

ALTER TABLE table_name RENAME TO new_table_name

(4)Change Column

ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]

這個命令可以允許改變列名、數據類型、註釋、列位置或者它們的任意組合

(5)Add/Replace Columns

ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)

ADD是代表新增一字段,字段位置在所有列後面(partition列前);REPLACE則是表示替換表中所有字段。

3).Show

查看錶名

SHOW TABLES;

查看錶名,部分匹配

SHOW TABLES 'page.*';
SHOW TABLES '.*view';

查看某表的所有Partition,如果沒有就報錯:

SHOW PARTITIONS page_view;

查看某表結構:

DESCRIBE invites;

查看分區內容

SELECT a.foo FROM invites a WHERE a.ds='2008-08-15';

查看有限行內容,同Greenplum,用limit關鍵詞

SELECT a.foo FROM invites a limit 3;

查看錶分區定義

DESCRIBE EXTENDED page_view PARTITION (ds='2008-08-08');

4).Load

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

Load 操作只是單純的複製/移動操作,將數據文件移動到 Hive 表對應的位置。

5).Insert

(1)Inserting data into Hive Tables from queries
    INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
(2)Writing data into filesystem from queries 
    INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...

6).Drop

刪除一個內部表的同時會同時刪除表的元數據和數據。刪除一個外部表,只刪除元數據而保留數據。

7).Limit

Limit 可以限制查詢的記錄數。查詢的結果是隨機選擇的

8).Select

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition] 
[GROUP BY col_list]
[   CLUSTER BY col_list
  | [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]

9).JOIN

join_table:
    table_reference JOIN table_factor [join_condition]
  | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
  | table_reference LEFT SEMI JOIN table_reference join_condition

table_reference:
    table_factor
  | join_table

table_factor:
    tbl_name [alias]
  | table_subquery alias
  | ( table_references )

join_condition:
    ON equality_expression ( AND equality_expression )*

equality_expression:
    expression = expression

7.HIVE內置函數


8. HIVE的UDF

  1. 新建java工程,導入hive相關包,導入hive相關的lib。
  2. 創建類繼承UDF
  3. 自己編寫一個evaluate方法,返回值和參數任意。
  4. 爲了能讓mapreduce處理,String要用Text處理。
  5. 將寫好的類打成jar包,上傳到linux中
  6. 在hive命令行下,向hive註冊UDF:add jar /xxxx/xxxx.jar
  7. 爲當前udf起一個名字:create temporary function fname as ‘類的全路徑名’;
  8. 之後就可以在hql中使用該自定義函數了。

9.案例

1).使用flume hive hadoop sqoop來處理zebra業務。

hadoop02 hadoop03:

#命名Agent a1的組件
        a1.sources=r1
        a1.sinks=k1
        a1.channels=c1
        #描述/配置Source
        a1.sources.r1.type=spooldir
        a1.sources.r1.spoolDir=/root/work/zebradata
        a1.sources.r1.interceptors=i1
        a1.sources.r1.interceptors.i1.type=timestamp
        #描述Sink
        a1.sinks.k1.type=avro
        a1.sinks.k1.hostname=192.168.242.201
        a1.sinks.k1.port=41414
        #描述內存Channel
        a1.channels.c1.type=memory
        a1.channels.c1.capacity  =  100000
        a1.channels.c1.transactionCapacity  =  100
        #爲Channel綁定Source和Sink
        a1.sources.r1.channels=c1
        a1.sinks.k1.channel=c1

hadoop01:

#命名Agent a1的組件
        a1.sources  =  r1
        a1.sinks  =  k1
        a1.channels  =  c1
        #描述/配置Source
        a1.sources.r1.type  = avro
        a1.sources.r1.bind  =  0.0.0.0
        a1.sources.r1.port  =  41414
        #描述Sink
        a1.sinks.k1.type  = hdfs
        a1.sinks.k1.hdfs.path = hdfs://CentOS01:9000/zebra/reportTime=%Y-%m-%d-%H-00-00
        a1.sinks.k1.hdfs.fileType = DataStream
        a1.sinks.k1.hdfs.minBlockReplicas=1
        a1.sinks.k1.hdfs.filePrefix = %Y-%m-%d-%H-%M-%S
        a1.sinks.k1.hdfs.fileSuffix = .data
        a1.sinks.k1.hdfs.rollInterval=10
        a1.sinks.k1.hdfs.rollSize=0
        a1.sinks.k1.hdfs.rollCount=0
        #描述內存Channel
        a1.channels.c1.type  =  memory
        a1.channels.c1.capacity  =  1000
        a1.channels.c1.transactionCapacity  =  100
        #爲Channle綁定Source和Sink
        a1.sources.r1.channels  =  c1
        a1.sinks.k1.channel  =  c1



./flume-ng agent --conf ../conf  -Xms128m -Xmx256m  --conf-file ../conf/zebra.conf --name a1 -Dflume.root.logger=INFO,console
可能出現的問題:
內存不足,解決方案,參看文檔。

2).使用hive處理數據

-----業務邏輯--------------------------------------------------------------------------------------------
//設置時間片信息
String reportTimeStr = attrs[0];
hah.setReportTime(new Timestamp(Long.parseLong(reportTimeStr)));
hah.setSlice(Long.parseLong(reportTimeStr));
//若cellId爲空,補全成000000000
if("".equals(hah.getCellid()) || hah.getCellid() == null){
    hah.setCellid("000000000");
}
//業務邏輯:嘗試次數 HTTP_ATTEMPT    attempts    if( App Type Code=103 ) then counter++
if(oi.getAppTypeCode() == 103){
    hah.setAttempts(1);
}

//業務邏輯:HTTP_Accept  accepts if( App Type Code=103 & HTTP/WAP事物狀態 in(10,11,12,13,14,15,32,33,34,35,36,37,38,48,49,50,51,52,53,54,55,199,200,201,202,203,204,205,206,302,304,306) && Wtp中斷類型==NULL) then counter++
    String code = ",10,11,12,13,14,15,32,33,34,35,36,37,38,48,49,50,51,52,53,54,55,199,200,201,202,203,204,205,206,302,304,306,";
    if(oi.getAppTypeCode() == 103 
            &&
            code.contains(","+oi.getTransStatus()+",")
            &&
            oi.getInterruptType() == null){
        hah.setAccepts(1);
    }

//業務邏輯:Traffic_UL_HTTP  trafficUL   if( App Type Code=103  ) then counter = counter + UL Data
//業務邏輯:traffic_DL_HTTP  trafficDL   if( App Type Code=103  ) then counter = counter + DL Data
//業務邏輯:Retran_UL    retranUL    if( App Type Code=103  ) then counter = counter + 上行TCP重傳報文數
//業務邏輯:Retran_DL    retranDL    if( App Type Code=103  ) then counter = counter + 下行TCP重傳報文數
if(oi.getAppTypeCode() == 103){
    hah.setTrafficUL(oi.getTrafficUL());
    hah.setTrafficDL(oi.getTrafficDL());
    hah.setRetranUL(oi.getRetranUL());
    hah.setRetranDL(oi.getRetranDL());
}


//業務邏輯:HTTP_Fail_Count  failCount   if( App Type Code=103 &&  HTTP/WAP事務狀態==1  &&  Wtp中斷類型==NULL ) then counter = counter + 1
if(oi.getAppTypeCode() == 103 && oi.getTransStatus() == 1 && oi.getInterruptType() == null){
    hah.setFailCount(1);
}
//設置TransDelay if( App Type Code=103  ) then counter = counter + (Procedure_End_time-Procedure_Start_time)
if(oi.getAppTypeCode() == 103){
    hah.setTransDelay(oi.getProcdureEndTime() - oi.getProcdureStartTime());
}
    -----------------------------------------------------------------------------------------------------
#創建原始數據表datasource

    create EXTERNAL table book (id bigint, name string) partitioned by (category string) row format delimited fields terminated by '\t' 

    --create EXTERNAL table zebra (a1 string,a2 string,a3 string,a4 string,a5 string,a6 string,a7 string,a8 string,a9 string,a10 string,a11 string,a12 string,a13 string,a14 string,a15 string,a16 string,a17 string,a18 string,a19 string,a20 string,a21 string,a22 string,a23 string,a24 string,a25 string,a26 string,a27 string,a28 string,a29 string,a30 string,a31 string,a32 string,a33 string,a34 string,a35 string,a36 string,a37 string,a38 string,a39 string,a40 string,a41 string,a42 string,a43 string,a44 string,a45 string,a46 string,a47 string,a48 string,a49 string,a50 string,a51 string,a52 string,a53 string,a54 string,a55 string,a56 string,a57 string,a58 string,a59 string,a60 string,a61 string,a62 string,a63 string,a64 string,a65 string,a66 string,a67 string,a68 string,a69 string,a70 string,a71 string,a72 string,a73 string,a74 string,a75 string,a76 string,a77 string) partitioned by (reportTime string) row format delimited fields terminated by '|' stored as textfile location '/zebra';

#導入原始數據
    --load data local inpath '../mydata/103_20150615143630_00_00_000_1.csv' into table datasource;  
    --ALTER TABLE zebra add  PARTITION (reportTime='2016-04-19-16-00-00') location '/zebra/reportTime=2016-04-19-16-00-00'; 


#進行數據清洗,將清晰過的數據存入dataclear
    create table dataclear (
        reporttime string,
        appType bigint,
        appSubtype bigint,
        userIp string,
        userPort bigint,
        appServerIP string,
        appServerPort bigint,
        host string,
        cellid string,

        appTypeCode bigint ,
        interruptType String,
        transStatus bigint,
        trafficUL bigint,
        trafficDL bigint,
        retranUL bigint,
        retranDL bigint,
        procdureStartTime bigint,
        procdureEndTime bigint
    ) row format delimited fields terminated by '|';
    --create table dataclear (reporttime string, appType bigint, appSubtype bigint, userIp string, userPort bigint, appServerIP string, appServerPort bigint, host string, cellid string,  appTypeCode bigint , interruptType String, transStatus bigint, trafficUL bigint, trafficDL bigint, retranUL bigint, retranDL bigint, procdureStartTime bigint, procdureEndTime bigint) row format delimited fields terminated by '|';


insert overwrite table dataclear 
    select 
    time,a23,a24,a27,a29,a31,a33,a59,a17,
        a19,a68,a55,a34,a35,a40,a41,a20,a21 
    from datasource;
--insert overwrite table dataclear select reportTime,a23,a24,a27,a29,a31,a33,a59,a17,a19,a68,a55,a34,a35,a40,a41,a20,a21 from zebra;    


#業務邏輯處理:
    create table dataproc (
        reporttime string,
        appType bigint,
        appSubtype bigint,
        userIp string,
        userPort bigint,
        appServerIP string,
        appServerPort bigint,
        host string,
        cellid string,

        attempts bigint,
        accepts bigint,
        trafficUL bigint,
        trafficDL bigint,
        retranUL bigint,
        retranDL bigint,
        failCount bigint,
        transDelay bigint
    )row format delimited fields terminated by '|';
    --create table dataproc (reporttime string,appType bigint,appSubtype bigint,userIp string,userPort bigint,appServerIP string,appServerPort bigint,host string,cellid string,attempts bigint,accepts bigint,trafficUL bigint,trafficDL bigint,retranUL bigint,retranDL bigint,failCount bigint,transDelay bigint)row format delimited fields terminated by '|';

    insert overwrite table dataproc 
        select 
            reporttime,
            appType,
            appSubtype,
            userIp,
            userPort,
            appServerIP,
            appServerPort,
            host,
            if(cellid == '','000000000',cellid),

            if(appTypeCode == 103,1,0),
            if(appTypeCode == 103 and find_in_set(transStatus,'10,11,12,13,14,15,32,33,34,35,36,37,38,48,49,50,51,52,53,54,55,199,200,201,202,203,204,205,206,302,304,306')!=0 and interruptType == 0,1,0),
            if(apptypeCode == 103,trafficUL,0), 
            if(apptypeCode == 103,trafficDL,0), 
            if(apptypeCode == 103,retranUL,0), 
            if(apptypeCode == 103,retranDL,0), 
            if(appTypeCode == 103 and transStatus == 1 and interruptType == 0,1,0),
            if(appTypeCode == 103, procdureEndTime - procdureStartTime,0) 
        from dataclear;
    --insert overwrite table dataproc select reporttime,appType,appSubtype,userIp,userPort,appServerIP,appServerPort,host,if(cellid == '',"000000000",cellid),if(appTypeCode == 103,1,0),if(appTypeCode == 103 and find_in_set(transStatus,"10,11,12,13,14,15,32,33,34,35,36,37,38,48,49,50,51,52,53,54,55,199,200,201,202,203,204,205,206,302,304,306")!=0 and interruptType == 0,1,0),if(apptypeCode == 103,trafficUL,0), if(apptypeCode == 103,trafficDL,0), if(apptypeCode == 103,retranUL,0), if(apptypeCode == 103,retranDL,0), if(appTypeCode == 103 and transStatus == 1 and interruptType == 0,1,0),if(appTypeCode == 103, procdureEndTime - procdureStartTime,0) from dataclear;


3).查詢關心的信息,以應用受歡迎程度表爲例:

create table D_H_HTTP_APPTYPE(
            hourid  string,
            appType bigint,
            appSubtype bigint,
            attempts bigint,
            accepts bigint,
            succRatio bigint,
            trafficUL bigint,
            trafficDL bigint,
            totalTraffic bigint,
            retranUL bigint,
            retranDL bigint,
            retranTraffic bigint,
            failCount bigint,
            transDelay bigint
        )row format delimited fields terminated by '|';


        --create table D_H_HTTP_APPTYPE(hourid string,appType bigint,appSubtype bigint,attempts bigint,accepts bigint,succRatio bigint,trafficUL bigint,trafficDL bigint,totalTraffic bigint,retranUL bigint,retranDL bigint,retranTraffic bigint,failCount bigint,transDelay bigint) row format delimited fields terminated by '|';

        --insert overwrite table D_H_HTTP_APPTYPE select reporttime,apptype,appsubtype,sum(attempts),sum(accepts),sum(accepts)/sum(attempts),sum(trafficUL),sum(trafficDL),sum(trafficUL)+sum(trafficDL),sum(retranUL),sum(retranDL),sum(retranUL)+sum(retranDL),sum(failCount),sum(transDelay)from dataproc group by reporttime,apptype,appsubtype;

4).利用sqoop技術將hdfs中的處理結果落地到mysql數據庫:

  • 在mysql中準備庫和表:
create database zebra;
use zebra;
create table D_H_HTTP_APPTYPE(hourid varchar(20),apptype bigint,appsubtype bigint,attempts bigint,accepts bigint,succratio bigint,trafficul bigint,trafficdl bigint,totaltraffic bigint,retranul bigint,retrandl bigint,retrantraffic bigint,failcount bigint,transdelay bigint);
  • 從hdfs中將數據導出到關係型數據庫中
sqoop export --connect jdbc:mysql://192.168.242.133:3306/zebra --username root --password root --export-dir '/user/hive/warehouse/zebra.db/d_h_http_apptype' --table D_H_HTTP_APPTYPE -m 1 --fields-terminated-by '|'
====================================================================    
  • sqoop 溝通hdfs和關係型數據庫的橋樑,可以從hdfs導出數據到關係型數據庫,也可以從關係型數據庫導入數據到hdfs

sqoop的使用:

下載:
Apache 提供的工具

安裝:

  • 要求必須有jdk 和 hadoop的支持,並且有版本要求。
  • 上傳到linux中,進行解壓
  • sqoop可以通過JAVA_HOME找到jdk 可以通過HADOOP_HOME找到hadoop所以不需要做任何配置就可以工作。
  • 需要將要連接的數據庫的驅動包加入sqoop的lib目錄下

從關係型數據庫導入數據到hdfs:

sqoop import --connect jdbc:mysql://192.168.1.10:3306/tedu --username root --password 123  --table trade_detail --columns 'id, account, income, expenses'

指定輸出路徑、指定數據分隔符

sqoop import --connect jdbc:mysql://192.168.1.10:3306/tedu --username root --password 123  --table trade_detail --target-dir '/sqoop/td' --fields-terminated-by '\t'

指定Map數量 -m

sqoop import --connect jdbc:mysql://192.168.1.10:3306/tedu --username root --password 123  --table trade_detail --target-dir '/sqoop/td1' --fields-terminated-by '\t' -m 2

增加where條件, 注意:條件必須用引號引起來

sqoop import --connect jdbc:mysql://192.168.1.10:3306/tedu --username root --password 123  --table trade_detail --where 'id>3' --target-dir '/sqoop/td2' 

增加query語句(使用 \ 將語句換行)

sqoop import --connect jdbc:mysql://192.168.1.10:3306/tedu --username root --password 123 --query 'SELECT * FROM trade_detail where id > 2 AND $CONDITIONS' --split-by trade_detail.id --target-dir '/sqoop/td3'

注意:

  • 如果使用–query這個命令的時候,需要注意的是where後面的參數,AND
    $CONDITIONS這個參數必須加上而且存在單引號與雙引號的區別
  • 如果–query後面使用的是雙引號,那麼需要在$CONDITIONS前加上\即\$CONDITIONS
  • 如果設置map數量爲1個時即-m 1,不用加上–split-by ${tablename.column},否則需要加上

從hdfs到處數據到關係型數據庫:

sqoop export --connect jdbc:mysql://192.168.8.120:3306/tedu --username root --password 123 --export-dir '/td3' --table td_bak -m 1 --fields-terminated-by ','
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章