1. 程式人生 > >Hive 編程之DDL、DML、UDF、Select總結

Hive 編程之DDL、DML、UDF、Select總結

jar包 dfs 5.1 hand let 算術運算 oca 創建表 需要

  Hive的基本理論與安裝可參看作者上一篇博文《Apache Hive 基本理論與安裝指南》。

一、Hive命令行

  所有的hive命令都可以通過hive命令行去執行,hive命令行中仍有許多選項。使用$hive -H查看:

技術分享圖片

  -e 選項後面可以直接接一個hql語句,不用進入到hive命令行用戶接口再輸入hql語句。

  -f 選項後面接一個hql語句的文件。

  -i 選項在hql語句執行之前的初始化hql文件。例如添加、導入等操作都可以寫在這個hql語句文件中。

  在hive使用中,大多是寫很多腳本,在hive命令行中輸入是屬於交互式的,這就必須有工作人員在工作,不適合做批量處理。可以使用-f或-i選項,一次性執行可以將所有的hql語句放在一個hql腳本文件中。例如:

$ mkdir -p /opt/shell/sql
$ vim /opt/shell/sql/test.sql
select * from table_name limit 5;
select * from table_name where professional="student";
select count(*) from table_name;
select count(*) from table_name group by professional;
select * from table_name where professional="student" order by
age;

  將腳本保存退出後,再批量執行:

$ hive -f /opt/shell/sql/test.sql

二、Hive DDL(Data Definition Language)

  • Hive Data Definition Language
    • Overview
    • Keywords, Non-reserved Keywords and Reserved Keywords
    • Create/Drop/Alter/Use Database
    • Create/Drop/Truncate Table
    • Alter Table/Partition/Column
    • Create/Drop/Alter View
    • Create/Drop/Alter Index
    • Create/Drop Macro
    • Create/Drop/Reload Function
    • Create/Drop/Grant/Revoke Roles and Privileges
    • Show
    • Describe
    • Abort
  • HCatalog and WebHCat DDL

  詳見官方文檔。重點在於創建表和創建函數。

1. 建表語法

  • 建表語句

  從官方文檔的Create Table中可以查看hive建表的命令,如下:

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name    -- (Note: TEMPORARY available in Hive 0.14.0 and later)
  [(col_name data_type [COMMENT col_comment], ... [constraint_specification])]
  [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]
  [SKEWED BY (col_name, col_name, ...)                  -- (Note: Available in Hive 0.10.0 and later)]
     ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
     [STORED AS DIRECTORIES]
  [
   [ROW FORMAT row_format] 
   [STORED AS file_format]
     | STORED BY storage.handler.class.name [WITH SERDEPROPERTIES (...)]  -- (Note: Available in Hive 0.6.0 and later)
  ]
  [LOCATION hdfs_path]
  [TBLPROPERTIES (property_name=property_value, ...)]   -- (Note: Available in Hive 0.6.0 and later)
  [AS select_statement];   -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
 
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
  LIKE existing_table_or_view_name
  [LOCATION hdfs_path];
  • 數據類型
data_type
  : primitive_type
  | array_type
  | map_type
  | struct_type
  | union_type  -- (Note: Available in Hive 0.7.0 and later)

  data_type,有兩種類型:一種是復雜類型,例如array_type(ARRAY < data_type >)、map_type(MAP < primitive_type, data_type >)、struct_type(STRUCT < col_name : data_type [COMMENT col_comment], ...>)、union_type(UNIONTYPE < data_type, data_type, ... >);簡單類型有SMALLINT(占2個字節的整數)、INT(占4個字節的整數)、BIGINT(占8個字節的整數)、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY、TIMESTAMP、DECIMAL、DATE、VARCHAR(0.12之後)、CHAR(字符,0.13之後)。

primitive_type
  : TINYINT
  | SMALLINT
  | INT
  | BIGINT
  | BOOLEAN
  | FLOAT
  | DOUBLE
  | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
  | STRING
  | BINARY      -- (Note: Available in Hive 0.8.0 and later)
  | TIMESTAMP   -- (Note: Available in Hive 0.8.0 and later)
  | DECIMAL     -- (Note: Available in Hive 0.11.0 and later)
  | DECIMAL(precision, scale)  -- (Note: Available in Hive 0.13.0 and later)
  | DATE        -- (Note: Available in Hive 0.12.0 and later)
  | VARCHAR     -- (Note: Available in Hive 0.12.0 and later)
  | CHAR        -- (Note: Available in Hive 0.13.0 and later)
  • row_format
row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]   -- (Note: Available in Hive 0.13 and later)
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

  row_format:需要指出每一行是由什麽隔開,並且要指出每一行中的每一個字段是用什麽隔開的。

  對於字段的隔開,復雜數據類型和簡單數據類型不一樣。例如數組類型是復雜類型,其隔開符[COLLECTION ITEMS TERMINATED BY char],Map類型的要使用[MAP KEYS TERMINATED BY char]。[LINES TERMINATED BY char]可以設置行隔開符,如果不寫,默認為回車換行。

  • file_format
file_format:
  : SEQUENCEFILE
  | TEXTFILE    -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE      -- (Note: Available in Hive 0.6.0 and later)
  | ORC         -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET     -- (Note: Available in Hive 0.13.0 and later)
  | AVRO        -- (Note: Available in Hive 0.14.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname

  SEQUENCEFILE表示序列壓縮格式,以及RCFILE、ORC、PARQUET、AVRO都是壓縮格式。TEXTFILE是默認的格式,文本格式。

2. 創建表案例一  

  • 查看數據

  為舉例說明,這裏先生成數據文件:

vim /root/person.txt
1,zhangsan,31,books-sports-math,city:shanghai-street:lujiazui-zipcode:313100
2,lisi,35,books-music,city:hangzhou-street:xihu-zipcode:222100
3,wangwu,25,computer-games,city:guangzhou-street:baiyun-zipcode:212300
  • 創建表

  根據數據創建一個人類表,包含人的編號、姓名、年齡、愛好、地址五個字段。

vim /opt/shell/sql/t_person.sql
create table t_person
(
    id int,
    name string,
    age int,
    likes array<string>,
    address map<string,string>
) row format delimited 
fields terminated by , 
collection items terminated by -
map keys terminated by : 
lines terminated by \n 
stored as textfile;

  根據表結構,字段之間按,隔開;likes的類型是array,所以可以有多個愛好,元素之間按-隔開,以,作為數組的結束;地址是map類型,也是collection類型, key和value按:隔開,每對key和value之間用-隔開(和collection一致);回車代表換行符。

  執行創建表腳本:

$ hive -f /opt/shell/sql/t_person.sql
  • 將數據從本地導入到hive
hive> load data local inpath /root/person.txt into table t_person;
  • 查看數據

技術分享圖片

3. 創建表案例二(分區表)

  當我們要在關系型數據庫中查找某一數據時,一般需要匹配數據庫中的所有數據,所以可以通過分區來提高查詢效率。把常用的查詢條件作為一種分區,例如要查某一天的數據,事實上就是可以只匹配當天的數據,其他數據不匹配。下面以建一個日誌管理表為例:

  • 數據文件

  文件經常按照天、小時等進行分割。故在此創建多個文件如下:

vim /root/log_2016-03-11.txt
111,1,200,2016-03-11
135,4,100,2016-03-11
211,3,300,2016-03-11
141,1,200,2016-03-11
131,2,400,2016-03-11
vim /root/log_2016-03-12.txt
121,2,300,2016-03-12
125,3,400,2016-03-12
211,1,400,2016-03-12
161,3,100,2016-03-12
171,5,200,2016-03-12
  • 創建表結構
create table t_log (id string,type int,pid string,logtime string)
partitioned by (day string)
row format delimited 
fields terminated by ,
stored as textfile;

  這裏指定了按照天做分區。

  • 裝載數據
hive> load data local inpath /root/log_2016-03-11.txt into table t_log partition (day=2016-03-11);
hive> load data local inpath /root/log_2016-03-12.txt into table t_log partition (day=2016-03-12);
  • 查看數據
hive> select * from t_log;

技術分享圖片

  從上圖可以看出,數據增加了一個字段,左邊是logtime,右邊是分區day。所以,添加一個分區可以理解為添加一個字段;但是又不同於添加一個字段,因為查詢按照分區做限定(查詢分區day=‘2016-03-11‘)時其他分區的數據不讀取,而如果是字段的話,需要每一條數據進行匹配過濾。也可以從瀏覽器看出創建分區表的目錄結構如下:

技術分享圖片

  創建分區,就會為每一個分區建一個目錄,所以在查詢時,只在限定的分區目錄裏查詢。

  查看某一天的數據量

hive> select count(*) from t_log where day=2016-03-11‘;

  查看某一個月的數據量

hive>select count(*) from t_log where day between xxx and xxx;

  當然,這裏需要先轉換格式,略。

三、Hive DML(Data Manipulation Language)

  • Hive Data Manipulation Language
    • Loading files into tables
      • Syntax
      • Synopsis
      • Notes
    • Inserting data into Hive Tables from queries
      • Syntax
      • Synopsis
      • Notes
      • Dynamic Partition Inserts
        • Example
        • Additional Documentation
    • Writing data into the filesystem from queries
      • Syntax
      • Synopsis
      • Notes
    • Inserting values into tables from SQL
      • Syntax
      • Synopsis
      • Examples
    • Update
      • Syntax
      • Synopsis
      • Notes
    • Delete
      • Syntax
      • Synopsis
      • Notes
    • Merge
      • Syntax
      • Synopsis
      • Performance Note
      • Notes
      • Examples

  詳見官方文檔。DML是對數據進行增刪改的腳本。但是數據在hdfs中,實際上不提供修改,只提供追加(insert),支持刪除。

1. Loading files into tables

  • 語法

  load file將數據導入到表中。其語法為:

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

  local:如果導入的數據在Linux主機本地,就要添加[local],如果數據已經在hdfs上就不能加local;overwrite:覆蓋;partition:如果表有分區就要加partition。

  • 實例
    • 將hdfs中的數據裝載到hive  

  首先,上傳Linux文件到hdfs

$ hdfs dfs -put /root/log_2016-03-1* /usr/input

  其次,在hive中執行導入

hive>load data inpath /usr/input/log_2016-03-12.txt into table t_log partition (day=2016-03-12);

技術分享圖片

hive>load data inpath /usr/input/log_2016-03-12.txt overwrite into table t_log partition (day=2016-03-12);

  註意:導入的分區要存在,導入到hive表後原來hdfs路徑下的文件就不復存在了,即存在hdfs的目錄變了,實際就是元數據變了,block的位置沒有變。如果使用overwrite,則原來該表中指定分區的數據將全部清空,然後上傳該文件。如果load相同文件名名到表中時,會默認生成副本filename_copy_1。文件中的數據格式要和表的結構相吻合。

    • 將Linux本地的數據裝載到hive
hive>load data local inpath /root/log_2016-03-11.txt into table t_log partition (day=2016-03-11);

2. Inserting data into hive tables from queries

  • 語法
hive> INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
hive> INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;

  其中的select_statement1 FROM from_statement;是一個sql語句。這是用於查詢hive中已經存在的數據,將查詢結果給到一張新表中。

hive> INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES values_row [, values_row ...] 

  這個語句是和關系型數據庫的insert語句用法是一樣的。區別有三:一是,有partition;二是,可以一次插入多條數據;三是,這種語句是轉成MapReduce去執行的。

  因為hive是一個工具,其作用是查詢和統計hdfs上的數據的,對於查詢結果一般就在控制臺上顯示,所以這個insert語句作用就是將查詢的結果保存下來,用於後期的展示。

  • 實例
hive> insert into table t_log partition (day=2016-03-13’) values (‘888‘,2,‘100‘,‘2016-03-13’); 

  這個會啟動MapReduce,因為數據在文件中不存在,要插到文件中相當於上傳,會生成一個新的文件。這個不常用。所以實際上inset into語句的實際意義在於將查詢結果放到新的表中。

3. Delete

  刪除數據一般可以不在hive中刪除,直接在hdfs上刪除文件。因為刪數據實際上就是刪除文件。例如要刪除之前插入到hive的t_log表day=2016-03-11分區下的log_2016-03-11.txt,可以執行如下命令:

#hdfs dfs -rm /user/hive/warehouse/t_log/day=2016-03-11/t_log-2016-03-11.txt

四、Hive UDF(Operators and User-Defined functions)

  • Hive Operators and User-Defined Functions (UDFs)
    • Built-in Operators
      • Operators Precedences
      • Relational Operators
      • Arithmetic Operators
      • Logical Operators
      • String Operators
      • Complex Type Constructors
      • Operators on Complex Types
    • Built-in Functions
      • Mathematical Functions
        • Mathematical Functions and Operators for Decimal Datatypes
      • Collection Functions
      • Type Conversion Functions
      • Date Functions
      • Conditional Functions
      • String Functions
      • Data Masking Functions
      • Misc. Functions
        • xpath
        • get_json_object
    • Built-in Aggregate Functions (UDAF)
    • Built-in Table-Generating Functions (UDTF)
      • Usage Examples
        • explode (array)
        • explode (map)
        • posexplode (array)
        • inline (array of structs)
        • stack (values)
      • explode
      • posexplode
      • json_tuple
      • parse_url_tuple
    • GROUPing and SORTing on f(column)
    • UDF internals
    • Creating Custom UDFs

  詳見官方文檔。

1. 內置運算符

  • 關系運算符

  見文檔

  • 算術運算符

  見文檔

  • 邏輯運算符

  見文檔

  • 復雜類型構造函數(Complex Type Constructors)
    • 復雜類型函數或對象的構建

  【1】map(構造map對象)

  Creates a map with the given key/value pairs. (key1,value1,key2,value2,…)

  【2】struct(創建架構數組)

  Creates a struct with the given field values. (val1,val2,val3,…)。Struct的屬性名和列名相對應。struct可以認為是面向對象的對象類型,是一個構造體,裏面可以定義屬性的值,field的名稱是預先定義的,就像Java類的屬性預先定義好了。

  【3】named_struct

  Creates a struct with the given field names and values. (name1,val1,name2,val2, …)。根據給定的Struct的屬性名來創建構建數組

  【4】array(創建數組對象)

  Creates an array with the given elements. (val1,val2,val3,…)。把各(若幹)個字段的值變成一個array。

  【5】create_union

  Creates a union type with value that is being pointes to by the tag parameter.

    • 復雜類型函數的運算符

  【1】A[n]

  A是array類型,n是int類型。A[n]表示數組A的第n+1個元素。

  【2】M[key]

  M是map類型,key是map集合中鍵的類型。M[key]是取map集合中鍵為key的值。註意使用是key需要使用單引號。

  【3】S.x

  S是struct類型,x表示struct中的某個屬性。S.x,將會返回S這個struct中定義的x屬性型中存儲的值。

2. 內置函數

  • 數學函數

技術分享圖片

  • 集合操作函數

技術分享圖片

  • 類型轉換函數

技術分享圖片

  • 日期函數

技術分享圖片

  • 條件/邏輯函數

  略。

  • 字符串函數

技術分享圖片

3. UDAF

  UDAF和UDF的區別在於傳給函數的參數不一樣。UDF表示傳給函數的參數只有一個值或一行值;UDAF是給函數傳多個值或者多行值的函數,例如count(*),sum(col)等都是多行的值。

  UDAF(User- Defined Aggregation Funcation) 聚集函數,多進一出,例如count/max/min等。

技術分享圖片

4. UDTF

  詳見文檔。

5. UDF

  HivePlugins,Creating Custom UDFs。自定義函數需要以下幾個步驟:首先要自定義一個類,繼承UDF;其次,打成jar包;第三,將jar包加載到hive的classpath;第四,創建自定義函數;第五,使用函數。

  例如,要創建一個將字符串轉成日期的函數。

  • 自定義類
package com.huidoo.hive;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.serde2.io.TimestampWritable;
import org.apache.hadoop.io.Text;

public class StringToDate extends UDF {
    /**
     * 定義evaluate方法。返回值類型定義為TimestampWritable
     * @param str
     * @param datefmt
     * @return
     * @throws Exception 
     */
    public TimestampWritable evaluate(final Text str,final Text datefmt) throws Exception{
        SimpleDateFormat sdf= new SimpleDateFormat(datefmt.toString()); //datefmt是傳入的格式化字符串,需要創建SimpleDateFormat對象,Text類型要轉成Java中的String類型。
        Date date= sdf.parse(str.toString()); //將字符串str,按照格式sdf轉成java.util的Date類型
        TimestampWritable time=new TimestampWritable();//創建Hadoop的時間戳對象
        time.setTime(date.getTime());//將date轉成Timestamp類型,然後使用Hadoop時間戳對象設置成相應的時間。
        return time;
    }
}
  • 打成jar包並上傳到服務器

  略。std.jar

  • 將jar包加載到hive的classpath
hive> add jar /path/to/std.jar;
  • 創建函數

  語法:create 函數名(不能與內置的一樣) as ‘自定義類的全限定名’;

hive> create function std as ‘com.huidoo.hive.StringToDate‘;

  這就創建了一個函數,名為std。

  • 使用函數
hive> select std(2016-02-06 01:19:30,yyyy-MM-dd HH:mm:ss) from t_log limit 3;

五、Hive Select

1. 簡單查詢和使用/切換數據庫

hive> select * from table_name;

  查看當前數據庫:

hive> SELECT current_database();

  "db_name.table_name" allows a query to access tables in different databases.可以查詢不同數據庫中的表。

  使用某數據庫:

hive> USE database_name;

2. where從句

hive>SELECT * FROM sales WHERE amount > 10 AND region = "US"

3. ALL and DISTINCT從句

  使用distinct關鍵字去重查詢,如下列出兩個查詢的區別:

hive> SELECT col1, col2 FROM t1

1 3

1 3

1 4

2 5

hive> SELECT DISTINCT col1, col2 FROM t1

1 3

1 4

2 5

4. Join從句

  join用於表連接。兩個表即兩個文件能連接起來就一定有相同點,這就是說其中一個文件中某域的值和另一個文件的某域的值相同,就可以連接。

hive> select col1,col2,col3 from t1 join t2 on+條件;

5. 基於Partition的查詢

  這種查詢語法就只要把partition當成一個字段即可。如果查詢時要引入外鍵關聯表也可以使用JION…ON語句。

  • 非關聯查詢

  語法:

hive> select table_name.* from table_name where table_name.partition_name +條件;

  案例:

SELECT page_views.*
FROM page_views
WHERE page_views.date >= 2016-03-01 AND page_views.date <= 2016-03-31
  • 關聯查詢

  語法:

hive> select table_name1.* from table_name1 join table_name2 on (table_name1.外鍵 = table_name2.主鍵 And table_name1.partiton_name +條件);

  案例:

SELECT page_views.*
FROM page_views JOIN dim_users 
ON (page_views.user_id = dim_users.id AND page_views.date >= 2016-03-01 AND page_views.date <= 2016-03-31);

6. Group by從句

hive> select col[list] from table_name group by col;

7. Order/Sort by從句

  sort by和order by的用法基本一致,都是做排序的,一般用order by。例如:

hive> select * from t_log order by id;

8. Having從句

  having從句必須依附於group by從句,在group從句後面接having從句,相當於增加一個條件。having後面可以接聚合函數,例如sum、avg等。

  • 單純的group by語句
hive> select day from t_log group by day;

  其查詢結果為:

  2016-03-11

  2016-03-12

  • 添加having從句
hive>select day from t_log group by day having avg(id)>150;

  其查詢結果為:

  2016-03-12

  • hiving同效於子查詢
hive> select day from (select day, avg(id) as avgid from t_log group by day) table2 where table2.avgid>150;

  這裏將t_log表通過select day, avg(id) as avgid from t_log group by day查詢得到的結果作為表再查詢的。和上述的hiving從句得到的結果一樣。

9. Limit從句

  限定查詢返回的行數。

hive> select * from t_log limit 5;

Hive 編程之DDL、DML、UDF、Select總結