1. 程式人生 > >大資料(二十二):hive分桶及抽樣查詢、自定義函式、壓縮與儲存

大資料(二十二):hive分桶及抽樣查詢、自定義函式、壓縮與儲存

一、分桶及抽樣查詢

1.分桶表資料儲存

        分割槽針對的是資料儲存路徑(HDFS中表現出來的便是資料夾),分桶針對的是資料檔案。分割槽提供一個隔離資料和優化查詢的便利方式。不過,並非所有的資料集都可形成合理的分割槽,特別是當資料要確定合適的劃分大小的時候,分割槽便不再合適。分桶是將資料集分解成更容易管理的若干部分的技術。

2.先建立分桶表,通過直接匯入資料的方式插入資料

建立分桶表

create table stu_buck(id int,name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';

查看錶結構

desc formatted stu_buck;

紅色標記出來的地方便是分桶的數量

將分桶功能開啟(預設為false)

set hive.enforce.bucketing = true;

設定reduce個數(設定成不限制)

set mapreduce.job.reduces=-1;

通過檔案匯入資料

load data local inpath '/opt/student.txt' into table stu_buck;

通過子查詢方式匯入資料(這裡的時候丟擲一個異常,重啟伺服器之後異常消失)

insert into table stu_buck select id,name from stu;

檢視hdfs目錄是否已經分桶

3.分桶取樣查詢

        對於非常大的資料集,有時使用者需要使用的是一個具有代表性的查詢結果而不是全部結果。Hive可以通過對錶進行抽樣來滿足這個需求。

select * from stu_buck TABLESAMPLE(bucket 1 out of 4 on id);

tablesample便是抽樣語句,語法:

TABLESAMPLE(BUCKET x OUT OF y);

        y必須是table總bucket數的倍數或者是因子。hive會根據y的大小,決定抽樣的比例。例如:table總共被分了4份,當y=2時,抽取(4/2=)2個bucket的資料,當y=8時,抽取(4/8=)1/2個bucket的資料。

        x則表示從哪個bucket開始抽樣。例如:table總bucket數為4,tablesample(bucket4 out of 4),表示總共抽取(4/4=)1個bucket的資料,抽取第4個bucket的資料。

這裡x的值必須小於等於y的值,否則會丟擲異常。

FAILED:SemanticException[Error 10061]:Numerator should not be bigger than denonminator in sample clause for table stu_buck

        hive還提供了另外一種按照百分百進行抽樣的方式,這種事基於行數的,按照輸入路徑下的資料塊百分比進行的取樣。

select * from stu tablesample(0.1 percent);

        這種抽樣方式不一定適合於所有的檔案格式。另外,這種抽樣的最小抽樣單元是一個HDFS資料。因此,如果這個表資料大小小於普通的的塊大小(128m)的話,那麼將會返回所有行。

 

二、函式

1.查詢系統中自帶的函式

show functions;

2.顯示自帶函式的用法

desc function {函式名};

3.詳細顯示自帶函式的用法

desc function extended{函式名};

4.自定義函式

我們可以通過UDF來完成自定義函式,根據自定義函式類別可以分為以下三種:

  1. UDF(User-Defined-Function)一進一出
  2. UDAF(User-Defined Aggregation Function)聚集函式,多進一出
  3. UDTF(User-Defined Table-Generating Functions)一進多出

程式設計步驟

  1. 繼承org.apache.hadoop.hive.ql.UDF
  2. 需要實現evaluate函式,evaluate函式支援過載
  3. 在hive的命令視窗建立函式
    1. 新增jar:add jar linux_jar_path
    2. 建立function:create [temporay] function [dbname.]function_name AS class_name;
  4. 在hive命令視窗刪除函式:Drop [temporay] function [if exists] [dbname.]function_name;

UDF必須有返回型別,可以返回Null,但是返回型別不能為void

5.自定義函式例項

        1.建立一個java工程

        2.將hive的jar包解壓後,將apache-hive-1.2.1-bin\lib資料夾下的jar包拷貝到java工程中。

        3.如果使用pom工程新增如下java包

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>1.2.1</version>
</dependency>

        4.建立類

public class Lower extends UDF {
    public String evaluate(final String s){
        if (s == null){
            return null;
        }
        return s.toLowerCase();
    }
}

        5.打成jar包上傳到hive所在伺服器

        6.新增jar包到hive中(hive命名行中)

add jar /opt/udf.jar

        7.建立臨時函式與開發好的java class關聯

create temporary function my_lower as 'com.gyx.hive.Lower';

        8.使用自定義的函式

select ename,my_lower(ename) lowername from emp;

 

三、壓縮和儲存

1.設定hadoop的壓縮配置

參照之前的部落格:https://blog.csdn.net/qq_34886352/article/details/82689965

2.開啟Map輸入階段的壓縮,可以減少job中map和Reduce task間資料傳輸量。

        1.開啟hive中間傳輸資料壓縮功能

set hive.exec.compress.intermediate=true;

        2.開啟mapreduce中map輸出壓縮功能

set mapreduce.map.output.compress=true;

        3.設定mapreduce中map輸出資料的壓縮方式

set mapreduce.map.outputcompress.codec={壓縮格式參照上面部落格的格式}

3.開啟reduce輸出階段壓縮

        當Hive將輸出寫入到表中時,輸出內容同樣可以進行壓縮。屬性hive.exec.compress.output控制這個功能,可以通過在查詢語句中或者執行指令碼中設定這個值為true。

        1.開啟hive最終輸出資料壓縮功能

set hive.exec.compress.output=true;

        2.開啟mapreduce最終輸出資料壓縮

set mapreduce.output.fileoutputformat.compress=true;

        3.設定mapreduce最終資料輸出壓縮方式

set mapreduce.output.fileoutputformat.compress.codec={壓縮格式參照上面部落格的格式}

        4.設定mapreduce最終資料輸出壓縮為塊壓縮

set mapreduce.output.fileoutputformat.compress.type=BLOCK;

 

四、儲存

1.檔案儲存格式

hive支援的檔案儲存的格式主要有:TEXTFILE、SEQUENCEFILE、ORC、PARQUET。

2.列式儲存和行式儲存

        行儲存的特點:查詢滿足條件的一整行資料的時候,列儲存則需要去每個聚集的欄位找到對應的每個列,行儲存只需要找到其中的一個值,其餘的值就在相鄰的地方,所以此時行儲存查詢的速度更快。

        列儲存的特點:應為每個欄位的資料聚集儲存,在查詢只需要少數幾個欄位的時候,能大大減少讀的資料量;每個欄位的資料型別一定是相同的,列式儲存可以針對性的設計更好的壓縮演算法。

        TEXTFILE和SEQUENCEFILE的儲存格式都是基於行儲存的。

        ORC和PARQUET是基於列式儲存的

3.TextFile格式

        預設格式,資料不做壓縮,磁碟開銷大,資料解析開銷大。可集合Gzip和Bzip2使用,但使用這種方式,hive不會對資料進行切分,從而無法對資料進行並行操作。

4.Orc格式

        ORC(Optimized Row Columnar)是hive0.11版裡引入的新的儲存格式。

        可以看到每個Orc檔案由1個或多個Stripe組成,每個Stripe250M大小,這個Stripe實際相對於RowGroup概念,不過大小由4MB->250MB,這樣能提升順序讀取的吞吐率。

每個Stripe裡有三部分組成,分別是Index Data,RowData,Stripe Footer:

        Index Data:一個輕量級的index,預設是每隔1W行做一個索引。這裡做的索引應該只是記錄某行的的個欄位的RowData中offset。

        Row Data:存的是具體的資料,先取部分行,然後對這些行按列進行儲存。對每個列進行了編碼,分成對多個Stream來儲存。

        StripeFooter:存的是各個Steam的型別,長度等資訊。

        每個檔案有一個FileFooter,這個在裡面存的是每個Stripe的行數,每個Column的資料型別資訊等;每個檔案的尾部是一個PostScript,這裡面記錄了整個檔案的壓縮型別以及FileFooter的長度資訊等。在讀取檔案時,會seek到檔案尾部讀PostScript。從裡面解析到FileFooter長度,在讀到FileFooter,從裡面解析到各個Stripe資訊,再讀各個Stripe,即從後往前讀。

5.Parquet格式

        parquet是面向分析型業務的列式儲存格式,由Twitter和Cloudera合作開發,2015年5月從Apache的卵化器裡畢業未Apache頂級專案。

        Parquet檔案是以二進位制方式儲存的,所有是不可以直接讀取的,檔案中包括該檔案的資料和元資料,因此Parquet格式檔案是自解析的。

        通常情況下,在儲存Parquet資料的時候會按照Block大小設定行組的大小,由於一般情況下每個Mapper任務處理資料的最小單位是一個Block,這樣可以把每一個行組由一個mapper任務處理,增大任務執行並行度。Parquet檔案格式如下

        一個檔案中可以儲存多個行組,檔案的首位都是該檔案MagicCode,用於校驗它是否是一個Parquet檔案,Footer length記錄了檔案元資料的大小,通過該值和檔案長度可以計算出元資料的偏移量,檔案的元資料中包括每一個行組的元資料資訊,和該檔案儲存資料的Schema資訊。除了檔案中每一個行組的元資料,每一夜的開始都會儲存該頁的元資料,在Parquet中,有三種類型的頁:資料頁、字典頁和索引頁。資料頁用於儲存當前行組中該列的值,字典頁儲存該列值的編碼字典,每一個列塊中最多包含一個字典頁,索引頁用來儲存當前行組下該列的索引。

6.主流檔案儲存格式對比

  • 儲存檔案壓縮比:ORC>Parquet>TextFile

  • 儲存檔案的速度對比:ORC>TextFile>Parquet(實際上三者幾乎一樣)