Hive入門詳解(二)

個人博客原文鏈接

Hive的DDL操作

創建表(四種表)

  1. 內部表
    創建產品表
create table t_product(id int,name string,price double,category string)
row format delimited
fields terminated by ','
stored as textfile;

導入數據(從本地)
load data local inpath '/home/hadoop/product_data' into table t_product;
導入數據(從hdfs)
load data inpath '/data/hive/test/product_data' into table t_product;
查看錶數據
select * from t_product;
刪除表
drop table t_product;

  1. 外部表
    創建手機表
create external table t_phone(id int,name string,price double)
row format delimited
fields terminated by ','
stored as textfile
location '/hive/test/'; 
注:在hdfs的指定位置上創建表

導入數據
load data local inpath '/home/hadoop/phone_data' into table t_phone;
  1. 分區表
創建表(分區表)
根據月份分區
create table t_order(id int,name string,cost double)
partitioned by (month string)
row format delimited 
fields terminated by ',';

導入數據到分區6
load data local inpath '/home/hadoop/phone_data' into table t_order
partition(month='6');

查看所有訂單的分區
show partitions t_order;
  1. 桶表
創建表(桶表)
create table t_product_bucket(id int,name string ,price string,category string)
clustered by(id) into 3 buckets
row format delimited 
fields terminated by ',';

桶表匯中的數據,只能從其他表中用子查詢進行插入
set hive.enforce.bucketing=true;
insert into table t_product_bucket select * from t_product;

查詢2上的數據
select * from t_product_bucket tablesample(bucket 2 out of 3 on id);

創建表(其它常用表)

  1. 子查詢創建表
create table t_product_back
as
select * from t_product;
  1. 數組
創建表(數組)
create table tab_array (a array<int>,b array<string>)
row format delimited
fields terminated by '\t'
collection items terminated by ',';

數據樣式
1,2,3   hello,world,briup

導入數據
load data local inpath '/home/hadoop/array_data' into table tab_array;

查詢數據
select a[2],b[1] from tab_array;
  1. map
創建表(map)
create table tab_map (name string,info map<string,string>)
row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';

數據樣式
zhangsan    name:zhangsan,age:18,gender:male

導入數據
load data local inpath '/home/hadoop/map_data' into table tab_map;

查詢數據
select  info['name'],info['gender'] from tab_map;
  1. struct
創建表(struct)
create table tab_struct(name string,info struct<age:int,tel:string,salary:double>)
row format delimited
fields terminated by '\t'
collection items terminated by ',';
 
數據樣式
zhangsan    18,18945883365,22.3

導入數據
load data local inpath '/home/hadoop/struct_data' into table tab_struct;

查詢數據
select info.age,info.tel from tab_struct;

修改表

  1. 增加/刪除分區
    alter table t_phone add partition(color='red');
    alter table t_phone drop partition(color='blue'),partirion(color='black');
  2. 重命名錶
    alter table t_phone rename to t_phone2;
  3. 增加/替換列
    alter table t_phone add colums (comment string);
    alter table t_phone replace colums (name string,price double);
    注:replace會替換該表的所有列

顯示命令

  • 展示表:show tables
  • 展示數據庫:show databases
  • 展示分區:show partitions
  • 展示內置函數:show functions

Hive的DML操作

Load

  1. 基本語法
    load [local] inpath '/home/hadoop/test_data' [overwrite] into table t_test
  2. local關鍵字
    如果指定了local關鍵字,local命令會去查找本地文件系統中的filepath,如果沒有指定local關鍵字,則根據inpath中的uri查找文件
  3. overwrite關鍵字
    目標表(或者分區)中的內容會被刪除,然後再將filepath指向的文件目錄中的內容添加到表/分區中,相當於覆蓋。

Insert

  1. 基本模式插入
insert overwrite table t_phone partition(color='red')
select name,price from t_test where color='red';
  1. 多插入模式
insert overwrite table t_phone partition(color='red')
select name,price from t_test where color='red'
insert overwrite table t_phone partition(color='blue')
select name,price from t_test where color='blue';
  1. 自動分區模式
insert overwrite table t_phone partition(color)
select name,price from t_test where color='red';
  1. 導出文件到本地
insert overwrite local directory '/home/hadoop/test/'
select * from t_phone;
  1. 導出數據到HDFS
insert overwrite directory 'hdfs://hadoop1:9000/hive/test'
select * from t_phone;

Select

  1. 準備範例
範例表big_data
create table big_data(id int,point double)
row format delimited
fields terminated by ','
stored as textfile;

範例數據
big_data
1,80.0
4,50.0
3,60.0
8,40.0
6,85.0
2,100.0
5,80.0
7,60.0

導入數據
load data local inpath '/home/hadoop/big_data' into table big_data;

查看數據
select * from big_data;
  1. 排序
    order by id asc 全局排序
    ex:
    select * from big_data order by id;
    注:order by會對輸入做全局排序,因此只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。

sort by id desc 局部排序
ex:
set mapred.reduce.tasks=2;
select * from big_data sort by id;

  1. 分區
    分區
    distribute by 按照指定的字段或表達式對數據進行劃分,輸出到對應的Reduce或者文件中,且分發的算法是hash散列
    ex:
    set mapred.reduce.tasks=2;
    insert overwrite local directory ‘/home/hadoop/data’
    select id from big_data
    distribute BY id;
    注:overwrite使用千萬注意,不要把家目錄給覆蓋了

  2. 分區+排序
    cluster by
    除了兼具distribute by的功能,還兼具sort by的排序功能
    ex:
    set mapred.reduce.tasks=2;
    insert overwrite local directory ‘/home/hadoop/data’
    select id from big_data
    cluster by id;

  3. 去重
    group by
    select point from big_data group by point;

distinct
select distinct point from big_data;
注:如果數據較多,distinct效率會更低一些,一般推薦使用group by。

  1. 虛擬列
    INPUT__FILE__NAME:數據對應的HDFS文件名;
    BLOCK__OFFSET__INSIDE__FILE:該行記錄在文件中的偏移量;
    ex:
    select id,INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE from big_data;

Join

Hive支持等值連接(equality join)、內連接(inner join)外連接(outer join)和(left/right join)。Hive不支持非等值的連接,因爲非等值連接非常難轉化到mapreduce任務。另外,Hive支持多於2個表的連接。

  1. 只支持等值join

  2. 可以join多於兩個表

    • 案例一:
      如果join中多個表的join的key是同一個,則join會被轉化爲單個mapreduce任務,如下所示,只使用了b.id作爲join key
    select a.name,b.name,c.name
    from a 
    join b on (a.id = b.id)
    join c on (c.id = b.id) 
    
    • 案例二:
      如果join中多個表的join的key不是同一個,則join會被轉化爲多個mapreduce任務,如下所示,b.id1作爲第一次join的條件,而b.id2作爲第二次join的條件。因此,會產生兩個mapreduce任務。
    select a.name,b.name,c.name
    from a 
    join b on (a.id = b.id1)
    join c on (c.id = b.id2) 
    
  3. join對應產生的mapreduce的邏輯
    reducer會緩存join序列中除了最後一個表的所有表的記錄,再通過最後一個表將結果序列化到文件系統。這一實現有助於在reduce端減少內存的使用量。實踐中,應該把最大的那個表寫在最後(否則會因爲緩存而浪費大量內存)

  4. join是不能交換位置的
    無論是left outer join還是right outer join,都是左外連接的,必須按照左連接的順序

  5. 具體實踐

    • 準備範例
    範例數據
    user_name_data
    1   zhangsan
    2   lisi
    3   wangwu
    
    範例表user_name
    create table user_name(id int,name string)
    row format delimited
    fields terminated by '\t'
    stored as textfile;
    
    導入數據
    load data local inpath '/home/hadoop/user_name_data' into table user_name;
    
    查看數據
    select * from user_name;
    
    範例數據
    user_age_data
    1   30
    2   29
    4   21
    
    範例表user_age
    create table user_age(id int,age int)
    row format delimited
    fields terminated by '\t'
    stored as textfile;
    
    導入數據
    load data local inpath '/home/hadoop/user_age_data' into table user_age;
    
    查看數據
    select * from user_age;
    
    • 內連接
    select a.id,
    a.name,
    b.age
    from user_name a
    inner join user_age b
    on (a.id = b.id);
    

    注:當b中找不到等值的a.id時,沒有輸出

    • 左外連接
    select a.id,
    a.name,
    b.age
    from user_name a
    left outer join user_age b
    on (a.id = b.id);
    

    注:當b中找不到等值的a.id時,記錄也會輸出:a.id,a.name,null

    • 右外連接
    select a.id,
    a.name,
    b.age
    from user_name a
    right outer join user_age b
    on (a.id = b.id);
    

    注:當b中找不到等值的a.id時,記錄也會輸出:null,null,b.age

    • 全外連接
    select a.id,
    a.name,
    b.age
    from user_name a
    full outer join user_age b
    on (a.id = b.id);
    

    注:當b中找不到等值的a.id時,記錄也會輸出:null,null,null

    • 半連接
    left semi join
    以left semi join關鍵字前面的表爲主表
    返回主表的KEY也在副表中的記錄
    相當於in和exists
    select a.id,
    a.name
    from user_name a
    left semi join user_age b
    on (a.id = b.id);
    --等價於:
    select a.id,
    a.name
    from user_name a
    where a.id in (select id from user_age);
    
    • 笛卡爾積關聯(CROSS JOIN)
    select a.id,
    a.name,
    b.age
    from user_name a
    cross join user_age b;
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章