1. 程式人生 > >Hive總結2(分割槽+分桶+查詢)

Hive總結2(分割槽+分桶+查詢)

Hive是一個數據倉庫 ,儲存的半結構化資料  文字。

Hive不支援:事務,不支援索引(但可以通過分桶實現快速的查詢,hash)

 類似的分佈的nosql(Not Only Sql資料庫:hbase - Phoinex(鳳凰)

   Hive的功能,就是做mapreduce。

分割槽:

就是在可控制的情況下,將資料放到不同的目錄下。

減小查詢的範圍。 並不能加快查詢的速度。還是要查詢所有隻是分了一個目錄。

    Stud.txt  > mary=cp 目錄下

分桶就是hash儲存。Id = > where id=S001

  將資料根據hashcode值進行分開儲存

查詢時對id進行hash得出結果,就知道放到了那個檔案下, 提高查詢的速度。

 用外部表的方式管理,保證元資料不會丟失。

1.分割槽

通過partition by(欄位名 欄位型別) - 分割槽最後會形成一個目錄。

 分割槽的欄位,不在源資料中出現,但是表的一部分

1.1建立一個分割槽表

hive> create table stud01(

    >   id string,

    >   name string,

    >   age int

    > )

    > partitioned by (grade string)

    > row format delimited

    > fields terminated by '\t';

1.2匯入資料

在匯入資料時,必須要通過partition提定分割槽的值:

hive> load data local inpath '${env:HOME}/stud.txt' into table stud01 partition(grade='2009');

1.3查詢分割槽資料

對於分割槽,可能每一個分割槽中的資料都非常的多:

分割槽查詢限制:預設情況下,在查詢時,可以不用帶分割槽的條件

使用者配置:

在使用者目錄下建立.hiverc值為:

hive.mapred.mode=nonstrict

修改成strict就必須要查詢時有分割槽的條件,修改成nonstrict可以不用寫:

hive>select * from stu01 where grade ="2009"

在 Hive-site.xml配置,可以統一使用。

1.4檢視分割槽

hive>show partitions stu01;

1.5建立多級目錄

hive> create table stud01(

    >   id string,

    >   name string,

    >   age int

    > )

    > partitioned by (grade string,major string)

    > row format delimited

    > fields terminated by '\t';

1.6動態分割槽

如果使用load匯入 資料,則分割槽的值,是使用者硬編碼指定,且無法動態。

但是如果從一個表,向另一個表中匯入資料,則可以動態的建立分割槽,但是分割槽的欄位,必須是最後一個欄位。

查詢是否支援動態的分割槽:

指定動態分割槽 mm=name;

hive> insert overwrite table stud03 partition(mm) select id,age,grade,major,name from stud02;

2.排序

3種關鍵字:

   Order - 全排,速度比較慢,預設使用一個reducer。

   Distribute by (..) 根據指定欄位的hash值%reduce個數 放到不同的檔案中。

       Distribute by (..) sort by(...) 排序,-部分排序(每一個reduce內部排序)。

   Cluster by = distrubte + sort (部分排序)

2.1.全排序

hive> insert overwrite local directory '${env:HOME}/out001'

>row format delimited

>fields terminated by '\t'

>select name ,id ,age from stu01 order by (name) asc;

可以指定asc(升序)預設,或是desc(降序)

2.2.部分排序

hive> insert overwrite local directory 'home/keys/out002'

> select * from stud01 distribute by(id) sort by (name);

 Cluster by (id) = distribute by(id) sort by(id)

3.分桶

關鍵字:distributed

3.1建立表

hive> create table stud02(

    >   id string,

    >   name string,

    >   age int

    > )

    > clustered by (id) into 3 buckets

    > row format delimited

    > fields terminated by '\t';

3.2檢視資料

hive> desc formatted stu002;

3.3匯入資料

如果一個表是分桶的,通過load匯入的資料,還是不會分桶的。

向一個分桶的表中的儲存資料,必須要使用 insert select ...從其他的資料表中查詢資料:

hive>insert overweite table stu002 select id,name,age from stu01 cluster by (id);

此時的表既排序又分桶。

4.儲存格式

行儲存和列儲存

資料

行儲存:

適合查詢所有的資料(快)

型別:textfile,squence,avro(json)

使用:mysql oracle

列儲存

適合查詢某一列的資料(快)

使用: orcfile,rcfile,parquet,hbase

4.1sequenceFile

匯入資料用insert不能用load,load是檔案copy不會寫成sequenceFile。

4.2avro

檢視 檔案::$ hdfs dfs -text '目錄'

4.3orcfile/rcfile二進位制檔案

hive> create table stud_orcfile(

    >   id string,

    >   name string,

    >   age int

    > )

    > stored as orcfile

    row format delimited 文字檔案,順序檔案需要指定,二進位制不需要

4.4parquet

hive> create table stud_parquet(

    >   id string,

    >   name string,

    >   age int

    > )

    > stored as parquet;

5.view

邏輯表,裡面沒有資料。不支援load資料。主要功能簡化查詢,封裝查詢,許可權。

 它的資料就來一個查詢

hive> create view v1 as select id,name,age from stu01;

show tables 可以顯示v1;

對於沒有指定別名的列會預設為_c0

hive > create view v2 as select count(1),name from stu01;

查詢

hive> select '_c0',name from v2; //注意要加上單引號。不加不通過

hive > create view v2 as select count(1) as cnt,name from stu01;//指定列名

6.連線查詢

在hive中執行查詢時,有一個建議:

  1:越小的表,在前面-進行 快取

  2:大的資料表,在後面進行mapreduce。

hive> select s.id as sid,s.name sname,b.id bid,b.name bname from stud_seq s left outer join books b on(s.id=b.sid);

hive> select s.id as sid,s.name sname,b.id bid,b.name bname from stud_seq s right outer join books b on(s.id=b.sid);

hive> select s.id as sid,s.name sname,b.id bid,b.name bname from stud_seq s full join outer  books b on(s.id=b.sid);

7.子查詢

只支援非相關子查詢,不支援相關子查詢。

非相關子查詢:子查詢可以獨立執行的。

相關子查詢:子語句不能拿出來被單獨執行,有依賴關係。

SELECT * FROM stud WHERE id IN(SELECT sid FROM books GROUP BY sid HAVING COUNT(sid)=0);

SELECT sid FROM books GROUP BY sid HAVING COUNT(sid)=2; 

SELECT * FROM stud WHERE (SELECT COUNT(1) FROM books WHERE books.sid=stud.id)=0;

SELECT COUNT(1) FROM books WHERE books.sid=stud.id

8.檢視執行計劃

通過explain + sql語句檢視sql的執行計劃